From dd91cb0f8e1831fbbe056a7e1a1ee677f5e3493a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Nov 2017 15:42:39 +0100 Subject: [PATCH 001/291] Begin implementing GLQueueRunner and GLRenderManager --- ext/native/native.vcxproj | 4 + ext/native/native.vcxproj.filters | 12 + ext/native/thin3d/GLQueueRunner.cpp | 217 +++++++++++++++++ ext/native/thin3d/GLQueueRunner.h | 260 ++++++++++++++++++++ ext/native/thin3d/GLRenderManager.cpp | 326 ++++++++++++++++++++++++++ ext/native/thin3d/GLRenderManager.h | 297 +++++++++++++++++++++++ ext/native/thin3d/thin3d_gl.cpp | 4 + 7 files changed, 1120 insertions(+) create mode 100644 ext/native/thin3d/GLQueueRunner.cpp create mode 100644 ext/native/thin3d/GLQueueRunner.h create mode 100644 ext/native/thin3d/GLRenderManager.cpp create mode 100644 ext/native/thin3d/GLRenderManager.h diff --git a/ext/native/native.vcxproj b/ext/native/native.vcxproj index 9ccbc1e644..3f520beb66 100644 --- a/ext/native/native.vcxproj +++ b/ext/native/native.vcxproj @@ -241,6 +241,8 @@ + + @@ -699,6 +701,8 @@ + + diff --git a/ext/native/native.vcxproj.filters b/ext/native/native.vcxproj.filters index bec0f42cee..d452261752 100644 --- a/ext/native/native.vcxproj.filters +++ b/ext/native/native.vcxproj.filters @@ -332,6 +332,12 @@ base + + thin3d + + + thin3d + @@ -799,6 +805,12 @@ ui + + thin3d + + + thin3d + diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp new file mode 100644 index 0000000000..ff4f90ccba --- /dev/null +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -0,0 +1,217 @@ +#include "GLQueueRunner.h" +#include "GLRenderManager.h" +#include "gfx_es2/gpu_features.h" +#include "math/dataconv.h" + +void GLQueueRunner::CreateDeviceObjects() { + +} + +void GLQueueRunner::DestroyDeviceObjects() { + +} + +void GLQueueRunner::RunInitSteps(const std::vector &steps) { + +} + +void GLQueueRunner::RunSteps(const std::vector &steps) { + for (int i = 0; i < steps.size(); i++) { + const GLRStep &step = *steps[i]; + switch (step.stepType) { + case GLRStepType::RENDER: + PerformRenderPass(step); + break; + case GLRStepType::COPY: + PerformCopy(step); + break; + case GLRStepType::BLIT: + PerformBlit(step); + break; + case GLRStepType::READBACK: + PerformReadback(step); + break; + case GLRStepType::READBACK_IMAGE: + PerformReadbackImage(step); + break; + } + delete steps[i]; + } +} + +void GLQueueRunner::LogSteps(const std::vector &steps) { + +} + + +void GLQueueRunner::PerformBlit(const GLRStep &step) { +} + +void GLQueueRunner::PerformRenderPass(const GLRStep &step) { + // Don't execute empty renderpasses. + if (step.commands.empty() && step.render.color == GLRRenderPassAction::KEEP && step.render.depthStencil == GLRRenderPassAction::KEEP) { + // Nothing to do. + return; + } + + // This is supposed to bind a vulkan render pass to the command buffer. + PerformBindFramebufferAsRenderTarget(step); + + int curWidth = step.render.framebuffer ? step.render.framebuffer->width : 0; // vulkan_->GetBackbufferWidth(); + int curHeight = step.render.framebuffer ? step.render.framebuffer->height : 0; // vulkan_->GetBackbufferHeight(); + + GLRFramebuffer *fb = step.render.framebuffer; + + GLint activeTexture = GL_TEXTURE0; + + auto &commands = step.commands; + for (const auto &c : commands) { + switch (c.cmd) { + case GLRRenderCommand::DEPTH: + if (c.depth.enabled) { + glEnable(GL_DEPTH_TEST); + glDepthMask(c.depth.write); + glDepthFunc(c.depth.func); + } else { + glDisable(GL_DEPTH_TEST); + } + break; + case GLRRenderCommand::BLEND: + if (c.blend.enabled) { + glEnable(GL_BLEND); + glBlendEquationSeparate(c.blend.funcColor, c.blend.funcAlpha); + glBlendFuncSeparate(c.blend.srcColor, c.blend.dstColor, c.blend.srcAlpha, c.blend.dstAlpha); + } else { + glDisable(GL_BLEND); + } + break; + case GLRRenderCommand::CLEAR: + if (c.clear.clearMask & GLR_ASPECT_COLOR) { + float color[4]; + Uint8x4ToFloat4(color, c.clear.clearColor); + glClearColor(color[0], color[1], color[2], color[3]); + } + if (c.clear.clearMask & GLR_ASPECT_DEPTH) { + glClearDepth(c.clear.clearZ); + } + if (c.clear.clearMask & GLR_ASPECT_STENCIL) { + glClearStencil(c.clear.clearStencil); + } + break; + case GLRRenderCommand::BLENDCOLOR: + glBlendColor(c.blendColor.color[0], c.blendColor.color[1], c.blendColor.color[2], c.blendColor.color[3]); + break; + case GLRRenderCommand::VIEWPORT: + // TODO: Support FP viewports through glViewportArrays + glViewport((GLint)c.viewport.vp.x, (GLint)c.viewport.vp.y, (GLsizei)c.viewport.vp.w, (GLsizei)c.viewport.vp.h); + glDepthRange(c.viewport.vp.minZ, c.viewport.vp.maxZ); + break; + case GLRRenderCommand::SCISSOR: + glScissor(c.scissor.rc.x, c.scissor.rc.y, c.scissor.rc.w, c.scissor.rc.h); + break; + case GLRRenderCommand::UNIFORM4F: + switch (c.uniform4.count) { + case 1: + glUniform1f(c.uniform4.loc, c.uniform4.v[0]); + break; + case 2: + glUniform2fv(c.uniform4.loc, 1, c.uniform4.v); + break; + case 3: + glUniform3fv(c.uniform4.loc, 1, c.uniform4.v); + break; + case 4: + glUniform4fv(c.uniform4.loc, 1, c.uniform4.v); + break; + } + break; + case GLRRenderCommand::UNIFORMMATRIX: + glUniformMatrix4fv(c.uniformMatrix4.loc, 1, false, c.uniformMatrix4.m); + break; + case GLRRenderCommand::STENCIL: + glStencilFunc(c.stencil.stencilFunc, c.stencil.stencilRef, c.stencil.stencilCompareMask); + glStencilOp(c.stencil.stencilSFail, c.stencil.stencilZFail, c.stencil.stencilPass); + glStencilMask(c.stencil.stencilWriteMask); + break; + case GLRRenderCommand::BINDTEXTURE: + { + GLint target = c.texture.slot; + if (target != activeTexture) { + glActiveTexture(target); + activeTexture = target; + } + glBindTexture(GL_TEXTURE_2D, c.texture.texture); + break; + } + case GLRRenderCommand::DRAW: + glDrawArrays(c.draw.mode, c.draw.first, c.draw.count); + break; + case GLRRenderCommand::DRAW_INDEXED: + if (c.drawIndexed.instances == 1) { + glDrawElements(c.drawIndexed.mode, c.drawIndexed.count, c.drawIndexed.indexType, c.drawIndexed.indices); + } + break; + } + } + if (activeTexture != GL_TEXTURE0) + glActiveTexture(GL_TEXTURE0); +} + +void GLQueueRunner::PerformCopy(const GLRStep &step) { + GLuint srcTex = 0; + GLuint dstTex = 0; + GLuint target = GL_TEXTURE_2D; + + const GLRect2D &srcRect = step.copy.srcRect; + const GLOffset2D &dstPos = step.copy.dstPos; + + GLRFramebuffer *src = step.copy.src; + GLRFramebuffer *dst = step.copy.src; + + int srcLevel = 0; + int dstLevel = 0; + int srcZ = 0; + int dstZ = 0; + int depth = 1; + + switch (step.copy.aspectMask) { + case GLR_ASPECT_COLOR: + srcTex = src->color.texture; + dstTex = dst->color.texture; + break; + case GLR_ASPECT_DEPTH: + target = GL_RENDERBUFFER; + srcTex = src->depth.texture; + dstTex = src->depth.texture; + break; + } +#if defined(USING_GLES2) +#ifndef IOS + glCopyImageSubDataOES( + srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ, + dstTex, target, dstLevel, dstPos.x, dstPos.y, dstZ, + srcRect.w, srcRect.h, depth); +#endif +#else + if (gl_extensions.ARB_copy_image) { + glCopyImageSubData( + srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ, + dstTex, target, dstLevel, dstPos.x, dstPos.y, dstZ, + srcRect.w, srcRect.h, depth); + } else if (gl_extensions.NV_copy_image) { + // Older, pre GL 4.x NVIDIA cards. + glCopyImageSubDataNV( + srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ, + dstTex, target, dstLevel, dstPos.x, dstPos.y, dstZ, + srcRect.w, srcRect.h, depth); + } +#endif +} + +void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) { + +} + +void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { + +} diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h new file mode 100644 index 0000000000..a691927a26 --- /dev/null +++ b/ext/native/thin3d/GLQueueRunner.h @@ -0,0 +1,260 @@ +#pragma once + +#include +#include + +#include "gfx/gl_common.h" +#include "thin3d/DataFormat.h" + +struct GLRViewport { + float x, y, w, h, minZ, maxZ; +}; + +struct GLRect2D { + int x, y, w, h; +}; + +struct GLOffset2D { + int x, y; +}; + +enum class GLRRenderCommand : uint8_t { + DEPTH, + STENCIL, + BLEND, + BLENDCOLOR, + UNIFORM4F, + UNIFORMMATRIX, + TEXTURESAMPLER, + VIEWPORT, + SCISSOR, + CLEAR, + BINDTEXTURE, + DRAW, + DRAW_INDEXED, + PUSH_CONSTANTS, +}; + +struct GLRRenderData { + GLRRenderCommand cmd; + union { + struct { + GLboolean enabled; + GLboolean write; + GLenum func; + } depth; + struct { + GLboolean enabled; + GLenum stencilOp; + GLenum stencilFunc; + uint8_t stencilWriteMask; + uint8_t stencilCompareMask; + uint8_t stencilRef; + GLenum stencilSFail; + GLenum stencilZFail; + GLenum stencilPass; + } stencil; + struct { + GLenum mode; // primitive + GLint buffer; + GLint first; + GLint count; + } draw; + struct { + GLenum mode; // primitive + GLint count; + GLint instances; + GLint indexType; + void *indices; + } drawIndexed; + struct { + GLint loc; + GLint count; + float v[4]; + } uniform4; + struct { + GLint loc; + float m[16]; + } uniformMatrix4; + struct { + uint32_t clearColor; + float clearZ; + int clearStencil; + int clearMask; // VK_IMAGE_ASPECT_COLOR_BIT etc + } clear; + struct { + int slot; + GLint texture; + } texture; + struct { + GLuint wrapU; + GLuint wrapV; + bool maxFilter; + bool minFilter; + bool mipFilter; + } textureSampler; + struct { + GLRViewport vp; + } viewport; + struct { + GLRect2D rc; + } scissor; + struct { + GLboolean enabled; + GLenum srcColor; + GLenum dstColor; + GLenum srcAlpha; + GLenum dstAlpha; + GLenum funcColor; + GLenum funcAlpha; + } blend; + struct { + float color[4]; + } blendColor; + }; +}; + +// Unlike in Vulkan, we can't create stuff on the main thread, but need to +// defer this too. A big benefit will be that we'll be able to do all creation +// at the start of the frame. +enum class GLRInitStepType : uint8_t { + CREATE_TEXTURE, + CREATE_SHADER, + CREATE_PROGRAM, + CREATE_BUFFER, + + TEXTURE_SUBDATA, + BUFFER_SUBDATA, +}; + +class GLRShader; +class GLRTexture; +class GLRProgram; + +struct GLRInitStep { + GLRInitStep(GLRInitStepType _type) : stepType(_type) {} + GLRInitStepType stepType; + union { + struct { + GLRTexture *texture; + int width; + int height; + // ... + } create_texture; + struct { + GLRShader *shader; + const char *code; + } create_shader; + struct { + GLRProgram *program; + GLRShader *vshader; + GLRShader *fshader; + } create_program; + }; +}; + +enum class GLRStepType : uint8_t { + RENDER, + COPY, + BLIT, + READBACK, + READBACK_IMAGE, +}; + +enum class GLRRenderPassAction { + DONT_CARE, + CLEAR, + KEEP, +}; + +class GLRFramebuffer; + +enum { + GLR_ASPECT_COLOR = 1, + GLR_ASPECT_DEPTH = 2, + GLR_ASPECT_STENCIL = 3, +}; + +struct GLRStep { + GLRStep(GLRStepType _type) : stepType(_type) {} + GLRStepType stepType; + std::vector commands; + union { + struct { + GLRFramebuffer *framebuffer; + GLRRenderPassAction color; + GLRRenderPassAction depthStencil; + uint32_t clearColor; + float clearDepth; + int clearStencil; + int numDraws; + } render; + struct { + GLRFramebuffer *src; + GLRFramebuffer *dst; + GLRect2D srcRect; + GLOffset2D dstPos; + int aspectMask; + } copy; + struct { + GLRFramebuffer *src; + GLRFramebuffer *dst; + GLRect2D srcRect; + GLRect2D dstRect; + int aspectMask; + GLboolean filter; + } blit; + struct { + int aspectMask; + GLRFramebuffer *src; + GLRect2D srcRect; + } readback; + struct { + GLint texture; + GLRect2D srcRect; + int mipLevel; + } readback_image; + }; +}; + +class GLQueueRunner { +public: + GLQueueRunner() {} + + void RunInitSteps(const std::vector &steps); + + void RunSteps(const std::vector &steps); + void LogSteps(const std::vector &steps); + + void CreateDeviceObjects(); + void DestroyDeviceObjects(); + + inline int RPIndex(GLRRenderPassAction color, GLRRenderPassAction depth) { + return (int)depth * 3 + (int)color; + } + + void CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels); + +private: + void PerformBindFramebufferAsRenderTarget(const GLRStep &pass); + void PerformRenderPass(const GLRStep &pass); + void PerformCopy(const GLRStep &pass); + void PerformBlit(const GLRStep &pass); + void PerformReadback(const GLRStep &pass); + void PerformReadbackImage(const GLRStep &pass); + + void LogRenderPass(const GLRStep &pass); + void LogCopy(const GLRStep &pass); + void LogBlit(const GLRStep &pass); + void LogReadback(const GLRStep &pass); + void LogReadbackImage(const GLRStep &pass); + + void ResizeReadbackBuffer(size_t requiredSize); + + GLint curFramebuffer_ = 0; + + // Readback buffer. Currently we only support synchronous readback, so we only really need one. + // We size it generously. + GLint readbackBuffer_ = 0; + int readbackBufferSize_ = 0; +}; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp new file mode 100644 index 0000000000..ba43fb1768 --- /dev/null +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -0,0 +1,326 @@ +#include + +#include "GLRenderManager.h" +#include "thread/threadutil.h" +#include "base/logging.h" + +#if 0 // def _DEBUG +#define VLOG ILOG +#else +#define VLOG(...) +#endif + +void GLCreateImage(GLRImage &img, int width, int height, GLuint format, bool color) { + +} + +void GLDeleter::Perform() { + for (auto shader : shaders) { + delete shader; + } + for (auto program : programs) { + delete program; + } + // .. +} + +GLRenderManager::GLRenderManager() { + for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { + + } +} + +GLRenderManager::~GLRenderManager() { + for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { + + } +} + +void GLRenderManager::ThreadFunc() { + setCurrentThreadName("RenderMan"); + int threadFrame = threadInitFrame_; + bool nextFrame = false; + bool firstFrame = true; + while (true) { + { + if (nextFrame) { + threadFrame++; + if (threadFrame >= MAX_INFLIGHT_FRAMES) + threadFrame = 0; + } + FrameData &frameData = frameData_[threadFrame]; + std::unique_lock lock(frameData.pull_mutex); + while (!frameData.readyForRun && run_) { + VLOG("PULL: Waiting for frame[%d].readyForRun", threadFrame); + frameData.pull_condVar.wait(lock); + } + if (!frameData.readyForRun && !run_) { + // This means we're out of frames to render and run_ is false, so bail. + break; + } + VLOG("PULL: frame[%d].readyForRun = false", threadFrame); + frameData.readyForRun = false; + // Previously we had a quick exit here that avoided calling Run() if run_ was suddenly false, + // but that created a race condition where frames could end up not finished properly on resize etc. + + // Only increment next time if we're done. + nextFrame = frameData.type == GLRRunType::END; + assert(frameData.type == GLRRunType::END || frameData.type == GLRRunType::SYNC); + } + VLOG("PULL: Running frame %d", threadFrame); + if (firstFrame) { + ILOG("Running first frame (%d)", threadFrame); + firstFrame = false; + } + Run(threadFrame); + VLOG("PULL: Finished frame %d", threadFrame); + } + + VLOG("PULL: Quitting"); +} + +void GLRenderManager::StopThread() { + // Since we don't control the thread directly, this will only pause the thread. + + + if (useThread_ && run_) { + run_ = false; + for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { + auto &frameData = frameData_[i]; + { + std::unique_lock lock(frameData.push_mutex); + frameData.push_condVar.notify_all(); + } + { + std::unique_lock lock(frameData.pull_mutex); + frameData.pull_condVar.notify_all(); + } + } + + // TODO: Wait for something here! + + ILOG("GL submission thread paused. Frame=%d", curFrame_); + + // Eat whatever has been queued up for this frame if anything. + Wipe(); + + // Wait for any fences to finish and be resignaled, so we don't have sync issues. + // Also clean out any queued data, which might refer to things that might not be valid + // when we restart... + for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { + auto &frameData = frameData_[i]; + if (frameData.readyForRun || frameData.steps.size() != 0) { + Crash(); + } + frameData.readyForRun = false; + for (size_t i = 0; i < frameData.steps.size(); i++) { + delete frameData.steps[i]; + } + frameData.steps.clear(); + + std::unique_lock lock(frameData.push_mutex); + while (!frameData.readyForFence) { + VLOG("PUSH: Waiting for frame[%d].readyForFence = 1 (stop)", i); + frameData.push_condVar.wait(lock); + } + } + } else { + ILOG("GL submission thread was already paused."); + } +} + +void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil) { + assert(insideFrame_); + // Eliminate dupes. + if (steps_.size() && steps_.back()->render.framebuffer == fb && steps_.back()->stepType == GLRStepType::RENDER) { + if (color != GLRRenderPassAction::CLEAR && depth != GLRRenderPassAction::CLEAR) { + // We don't move to a new step, this bind was unnecessary and we can safely skip it. + return; + } + } + if (curRenderStep_ && curRenderStep_->commands.size() == 0 && curRenderStep_->render.color == GLRRenderPassAction::KEEP && curRenderStep_->render.depthStencil == GLRRenderPassAction::KEEP) { + // Can trivially kill the last empty render step. + assert(steps_.back() == curRenderStep_); + delete steps_.back(); + steps_.pop_back(); + curRenderStep_ = nullptr; + } + if (curRenderStep_ && curRenderStep_->commands.size() == 0) { + VLOG("Empty render step. Usually happens after uploading pixels.."); + } + + GLRStep *step = new GLRStep{ GLRStepType::RENDER }; + // This is what queues up new passes, and can end previous ones. + step->render.framebuffer = fb; + step->render.color = color; + step->render.depthStencil = depth; + step->render.clearColor = clearColor; + step->render.clearDepth = clearDepth; + step->render.clearStencil = clearStencil; + step->render.numDraws = 0; + steps_.push_back(step); + + curRenderStep_ = step; + curWidth_ = fb ? fb->width : 0; // vulkan_->GetBackbufferWidth(); + curHeight_ = fb ? fb->height : 0; // vulkan_->GetBackbufferHeight(); +} + +GLuint GLRenderManager::BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment) { + // Easy in GL. + return fb->color.texture; +} + +void GLRenderManager::CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLOffset2D dstPos, int aspectMask) { + +} + +void GLRenderManager::BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLRect2D dstRect, int aspectMask, bool filter) { + +} + +void GLRenderManager::BeginFrame() { + VLOG("BeginFrame"); + + int curFrame = GetCurFrame(); + FrameData &frameData = frameData_[curFrame]; + + // Make sure the very last command buffer from the frame before the previous has been fully executed. + if (useThread_) { + std::unique_lock lock(frameData.push_mutex); + while (!frameData.readyForFence) { + VLOG("PUSH: Waiting for frame[%d].readyForFence = 1", curFrame); + frameData.push_condVar.wait(lock); + } + frameData.readyForFence = false; + } + + VLOG("PUSH: Fencing %d", curFrame); + + // vkWaitForFences(device, 1, &frameData.fence, true, UINT64_MAX); + // vkResetFences(device, 1, &frameData.fence); + + // Must be after the fence - this performs deletes. + VLOG("PUSH: BeginFrame %d", curFrame); + if (!run_) { + WLOG("BeginFrame while !run_!"); + } + + // vulkan_->BeginFrame(); + frameData.deleter.Perform(); + + insideFrame_ = true; +} + +void GLRenderManager::Finish() { + curRenderStep_ = nullptr; + int curFrame = GetCurFrame(); + FrameData &frameData = frameData_[curFrame]; + if (!useThread_) { + frameData.steps = std::move(steps_); + frameData.type = GLRRunType::END; + Run(curFrame); + } else { + std::unique_lock lock(frameData.pull_mutex); + VLOG("PUSH: Frame[%d].readyForRun = true", curFrame); + frameData.steps = std::move(steps_); + frameData.readyForRun = true; + frameData.type = GLRRunType::END; + frameData.pull_condVar.notify_all(); + } + + // vulkan_->EndFrame(); + frameData_[curFrame_].deleter.Take(deleter_); + + curFrame_++; + + insideFrame_ = false; +} + +void GLRenderManager::BeginSubmitFrame(int frame) { + FrameData &frameData = frameData_[frame]; + if (!frameData.hasBegun) { + frameData.hasBegun = true; + } +} + +void GLRenderManager::Submit(int frame, bool triggerFence) { + FrameData &frameData = frameData_[frame]; + + // In GL, submission happens automatically in Run(). + + // When !triggerFence, we notify after syncing with Vulkan. + if (useThread_ && triggerFence) { + VLOG("PULL: Frame %d.readyForFence = true", frame); + std::unique_lock lock(frameData.push_mutex); + frameData.readyForFence = true; + frameData.push_condVar.notify_all(); + } +} + +void GLRenderManager::EndSubmitFrame(int frame) { + FrameData &frameData = frameData_[frame]; + frameData.hasBegun = false; + + Submit(frame, true); + + if (!frameData.skipSwap) { + // glSwapBuffers(); + } else { + frameData.skipSwap = false; + } +} + +void GLRenderManager::Run(int frame) { + BeginSubmitFrame(frame); + + FrameData &frameData = frameData_[frame]; + auto &stepsOnThread = frameData_[frame].steps; + auto &initStepsOnThread = frameData_[frame].initSteps; + // queueRunner_.LogSteps(stepsOnThread); + queueRunner_.RunInitSteps(initStepsOnThread); + queueRunner_.RunSteps(stepsOnThread); + stepsOnThread.clear(); + initStepsOnThread.clear(); + + switch (frameData.type) { + case GLRRunType::END: + EndSubmitFrame(frame); + break; + + case GLRRunType::SYNC: + EndSyncFrame(frame); + break; + + default: + assert(false); + } + + VLOG("PULL: Finished running frame %d", frame); +} + +void GLRenderManager::EndSyncFrame(int frame) { + FrameData &frameData = frameData_[frame]; + Submit(frame, false); + + // This is brutal! Should probably wait for a fence instead, not that it'll matter much since we'll + // still stall everything. + glFinish(); + // vkDeviceWaitIdle(vulkan_->GetDevice()); + + // At this point we can resume filling the command buffers for the current frame since + // we know the device is idle - and thus all previously enqueued command buffers have been processed. + // No need to switch to the next frame number. + + if (useThread_) { + std::unique_lock lock(frameData.push_mutex); + frameData.readyForFence = true; + frameData.push_condVar.notify_all(); + } +} + +void GLRenderManager::Wipe() { + for (auto step : steps_) { + delete step; + } + steps_.clear(); +} \ No newline at end of file diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h new file mode 100644 index 0000000000..43bdaeaeb8 --- /dev/null +++ b/ext/native/thin3d/GLRenderManager.h @@ -0,0 +1,297 @@ +#pragma once + +#include +#include + +#include "gfx/gl_common.h" +#include "math/dataconv.h" +#include "Common/Log.h" +#include "GLQueueRunner.h" + +struct GLRImage { + GLuint texture; + GLuint format; +}; + +void GLCreateImage(GLRImage &img, int width, int height, GLint format, bool color); + +class GLRFramebuffer { +public: + GLRFramebuffer(int _width, int _height) { + width = _width; + height = _height; + + /* + CreateImage(vulkan_, initCmd, color, width, height, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); + CreateImage(vulkan_, initCmd, depth, width, height, vulkan_->GetDeviceInfo().preferredDepthStencilFormat, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false); + + VkFramebufferCreateInfo fbci{ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO }; + VkImageView views[2]{}; + + fbci.renderPass = renderPass; + fbci.attachmentCount = 2; + fbci.pAttachments = views; + views[0] = color.imageView; + views[1] = depth.imageView; + fbci.width = width; + fbci.height = height; + fbci.layers = 1; + + vkCreateFramebuffer(vulkan_->GetDevice(), &fbci, nullptr, &framebuf);*/ + } + + ~GLRFramebuffer() { + glDeleteTextures(1, &color.texture); + glDeleteRenderbuffers(1, &depth.texture); + } + + int numShadows = 1; // TODO: Support this. + + GLuint framebuf = 0; + GLRImage color{}; + GLRImage depth{}; + int width = 0; + int height = 0; +}; + +// We need to create some custom heap-allocated types so we can forward things that need to be created on the GL thread, before +// they've actually been created. + +class GLRShader { +public: + ~GLRShader() { + if (shader) { + glDeleteShader(shader); + } + } + GLuint shader = 0; +}; + +class GLRProgram { +public: + ~GLRProgram() { + if (program) { + glDeleteProgram(program); + } + } + GLuint program = 0; +}; + +class GLRTexture { +public: + ~GLRTexture() { + if (texture) { + glDeleteTextures(1, &texture); + } + } + GLuint texture; +}; + +class GLRBuffer { +public: + ~GLRBuffer() { + if (texture) { + glDeleteTextures(1, &texture); + } + } + GLuint texture; +}; + +enum class GLRRunType { + END, + SYNC, +}; + +class GLDeleter { +public: + void Perform(); + + void Take(GLDeleter &other) { + shaders = std::move(other.shaders); + programs = std::move(other.programs); + } + + std::vector shaders; + std::vector programs; +}; + + +class GLRenderManager { +public: + GLRenderManager(); + ~GLRenderManager(); + + void ThreadFunc(); + + // Makes sure that the GPU has caught up enough that we can start writing buffers of this frame again. + void BeginFrame(); + // Can run on a different thread! + void Finish(); + void Run(int frame); + + // Zaps queued up commands. Use if you know there's a risk you've queued up stuff that has already been deleted. Can happen during in-game shutdown. + void Wipe(); + + // Creation commands. These were not needed in Vulkan since there we can do that on the main thread. + GLRTexture *CreateTexture(int w, int h) { + GLRInitStep step{ GLRInitStepType::CREATE_TEXTURE }; + step.create_texture.texture = new GLRTexture(); + step.create_texture.width = w; + step.create_texture.height = h; + initSteps_.push_back(step); + return step.create_texture.texture; + } + + GLRShader *CreateShader(const char *code) { + GLRInitStep step{ GLRInitStepType::CREATE_SHADER }; + step.create_shader.shader = new GLRShader(); + step.create_shader.code = code; + initSteps_.push_back(step); + return step.create_shader.shader; + } + + GLRProgram *CreateProgram(GLRShader *vshader, GLRShader *fshader) { + GLRInitStep step{ GLRInitStepType::CREATE_PROGRAM }; + step.create_program.program = new GLRProgram(); + step.create_program.vshader = vshader; + step.create_program.fshader = fshader; + initSteps_.push_back(step); + return step.create_program.program; + } + + void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil); + GLuint BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment); + bool CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride); + void CopyImageToMemorySync(GLuint texture, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride); + + void CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLOffset2D dstPos, int aspectMask); + void BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLRect2D dstRect, int aspectMask, bool filter); + + void SetViewport(const GLRViewport &vp) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::VIEWPORT }; + data.viewport.vp = vp; + curRenderStep_->commands.push_back(data); + } + + void SetScissor(const GLRect2D &rc) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::SCISSOR }; + data.scissor.rc = rc; + curRenderStep_->commands.push_back(data); + } + + void SetStencil(bool enabled, uint8_t writeMask, uint8_t compareMask, uint8_t refValue) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::STENCIL }; + data.stencil.stencilWriteMask = writeMask; + data.stencil.stencilCompareMask = compareMask; + data.stencil.stencilRef = refValue; + curRenderStep_->commands.push_back(data); + } + + void SetBlendFactor(float color[4]) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::BLENDCOLOR }; + CopyFloat4(data.blendColor.color, color); + curRenderStep_->commands.push_back(data); + } + + void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::CLEAR }; + data.clear.clearMask = clearMask; + data.clear.clearColor = clearColor; + data.clear.clearZ = clearZ; + data.clear.clearStencil = clearStencil; + curRenderStep_->commands.push_back(data); + } + + void Draw(GLenum mode, int first, int count) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::DRAW }; + data.draw.mode = mode; + data.draw.first = first; + data.draw.count = count; + data.draw.buffer = 0; + curRenderStep_->commands.push_back(data); + curRenderStep_->render.numDraws++; + } + + void DrawIndexed(GLenum mode, int count, GLenum indexType, void *indices) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::DRAW_INDEXED }; + data.drawIndexed.mode = mode; + data.drawIndexed.count = count; + data.drawIndexed.indexType = indexType; + data.drawIndexed.instances = 1; + data.drawIndexed.indices = indices; + curRenderStep_->commands.push_back(data); + curRenderStep_->render.numDraws++; + } + + enum { MAX_INFLIGHT_FRAMES = 3 }; + +private: + void BeginSubmitFrame(int frame); + void EndSubmitFrame(int frame); + void Submit(int frame, bool triggerFence); + + // Bad for performance but sometimes necessary for synchronous CPU readbacks (screenshots and whatnot). + void FlushSync(); + void EndSyncFrame(int frame); + + void StopThread(); + + int GetCurFrame() const { + return curFrame_; + } + + // Per-frame data, round-robin so we can overlap submission with execution of the previous frame. + struct FrameData { + std::mutex push_mutex; + std::condition_variable push_condVar; + + std::mutex pull_mutex; + std::condition_variable pull_condVar; + + bool readyForFence = true; + bool readyForRun = false; + bool skipSwap = false; + GLRRunType type = GLRRunType::END; + + // GLuint fence; For future AZDO stuff? + std::vector steps; + std::vector initSteps; + + // Swapchain. + bool hasBegun = false; + uint32_t curSwapchainImage = -1; + + GLDeleter deleter; + }; + + FrameData frameData_[MAX_INFLIGHT_FRAMES]; + + // Submission time state + int curWidth_; + int curHeight_; + bool insideFrame_ = false; + GLRStep *curRenderStep_ = nullptr; + std::vector steps_; + std::vector initSteps_; + + // Execution time state + bool run_ = true; + // Thread is managed elsewhere, and should call ThreadFunc. + std::mutex mutex_; + int threadInitFrame_ = 0; + GLQueueRunner queueRunner_; + + GLDeleter deleter_; + + bool useThread_ = false; + + int curFrame_ = 0; +}; + diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 95f9f6532a..c2accb0479 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -14,6 +14,8 @@ #include "gfx/GLStateCache.h" #include "gfx_es2/gpu_features.h" +#include "thin3d/GLRenderManager.h" + #ifdef IOS extern void bindDefaultFBO(); #endif @@ -546,6 +548,8 @@ private: void fbo_unbind(); void ApplySamplers(); + GLRenderManager renderManager_; + std::vector boundSamplers_; OpenGLTexture *boundTextures_[8]{}; int maxTextures_ = 0; From dc72a8696f4ccbd9a09518d88fb466153308837d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Nov 2017 16:50:49 +0100 Subject: [PATCH 002/291] More work on gl-render-manager --- ext/native/thin3d/GLQueueRunner.cpp | 108 +++++++++++++++++- ext/native/thin3d/GLQueueRunner.h | 64 +++++++---- ext/native/thin3d/GLRenderManager.h | 71 ++++++++++-- ext/native/thin3d/thin3d_gl.cpp | 163 +++++++--------------------- 4 files changed, 244 insertions(+), 162 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index ff4f90ccba..bdea224380 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -1,5 +1,7 @@ #include "GLQueueRunner.h" #include "GLRenderManager.h" +#include "base/logging.h" +#include "gfx/gl_common.h" #include "gfx_es2/gpu_features.h" #include "math/dataconv.h" @@ -12,7 +14,90 @@ void GLQueueRunner::DestroyDeviceObjects() { } void GLQueueRunner::RunInitSteps(const std::vector &steps) { + for (int i = 0; i < steps.size(); i++) { + const GLRInitStep &step = steps[i]; + switch (step.stepType) { + case GLRInitStepType::CREATE_TEXTURE: + break; + case GLRInitStepType::CREATE_PROGRAM: + { + GLRProgram *program = step.create_program.program; + program->program = glCreateProgram(); + for (int i = 0; i < step.create_program.num_shaders; i++) { + glAttachShader(program->program, step.create_program.shaders[i]->shader); + } + for (auto iter : program->semantics_) { + glBindAttribLocation(program->program, iter.location, iter.attrib); + } + glLinkProgram(program->program); + + GLint linkStatus = GL_FALSE; + glGetProgramiv(program->program, GL_LINK_STATUS, &linkStatus); + if (linkStatus != GL_TRUE) { + GLint bufLength = 0; + glGetProgramiv(program->program, GL_INFO_LOG_LENGTH, &bufLength); + if (bufLength) { + char* buf = new char[bufLength]; + glGetProgramInfoLog(program->program, bufLength, NULL, buf); + ELOG("Could not link program:\n %s", buf); + // We've thrown out the source at this point. Might want to do something about that. +#ifdef _WIN32 + OutputDebugStringUTF8(buf); +#endif + delete[] buf; + } else { + ELOG("Could not link program with %d shaders for unknown reason:", step.create_program.num_shaders); + } + break; + } + + // Auto-initialize samplers. + glUseProgram(program->program); + for (int i = 0; i < 4; i++) { + char temp[256]; + sprintf(temp, "Sampler%i", i); + int samplerLoc = glGetUniformLocation(program->program, temp); + if (samplerLoc != -1) { + glUniform1i(samplerLoc, i); + } + } + + // Here we could (using glGetAttribLocation) save a bitmask about which pieces of vertex data are used in the shader + // and then AND it with the vertex format bitmask later... + } + break; + case GLRInitStepType::CREATE_SHADER: + { + GLuint shader = glCreateShader(step.create_shader.stage); + step.create_shader.shader->shader = shader; + // language_ = language; + const char *code = step.create_shader.code; + glShaderSource(shader, 1, &code, nullptr); + delete[] code; + glCompileShader(shader); + GLint success = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (!success) { +#define MAX_INFO_LOG_SIZE 2048 + GLchar infoLog[MAX_INFO_LOG_SIZE]; + GLsizei len = 0; + glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog); + infoLog[len] = '\0'; + glDeleteShader(shader); + shader = 0; + ILOG("%s Shader compile error:\n%s", step.create_shader.stage == GL_FRAGMENT_SHADER ? "Fragment" : "Vertex", infoLog); + } + break; + } + case GLRInitStepType::CREATE_BUFFER: + glGenBuffers(1, &step.create_buffer.buffer->buffer); + break; + + case GLRInitStepType::TEXTURE_SUBDATA: + break; + } + } } void GLQueueRunner::RunSteps(const std::vector &steps) { @@ -54,6 +139,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { return; } + glEnable(GL_SCISSOR_TEST); + // This is supposed to bind a vulkan render pass to the command buffer. PerformBindFramebufferAsRenderTarget(step); @@ -129,9 +216,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glUniformMatrix4fv(c.uniformMatrix4.loc, 1, false, c.uniformMatrix4.m); break; case GLRRenderCommand::STENCIL: - glStencilFunc(c.stencil.stencilFunc, c.stencil.stencilRef, c.stencil.stencilCompareMask); - glStencilOp(c.stencil.stencilSFail, c.stencil.stencilZFail, c.stencil.stencilPass); - glStencilMask(c.stencil.stencilWriteMask); + glStencilFunc(c.stencil.func, c.stencil.ref, c.stencil.compareMask); + glStencilOp(c.stencil.sFail, c.stencil.zFail, c.stencil.pass); + glStencilMask(c.stencil.writeMask); break; case GLRRenderCommand::BINDTEXTURE: { @@ -140,7 +227,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glActiveTexture(target); activeTexture = target; } - glBindTexture(GL_TEXTURE_2D, c.texture.texture); + glBindTexture(GL_TEXTURE_2D, c.texture.texture->texture); + break; + } + case GLRRenderCommand::BINDPROGRAM: + { + glUseProgram(c.program.program->program); break; } case GLRRenderCommand::DRAW: @@ -208,6 +300,14 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) { #endif } +void GLQueueRunner::PerformReadback(const GLRStep &pass) { + +} + +void GLQueueRunner::PerformReadbackImage(const GLRStep &pass) { + +} + void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) { } diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index a691927a26..e16ada4562 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -18,6 +18,9 @@ struct GLOffset2D { int x, y; }; +class GLRProgram; +class GLRTexture; + enum class GLRRenderCommand : uint8_t { DEPTH, STENCIL, @@ -28,7 +31,9 @@ enum class GLRRenderCommand : uint8_t { TEXTURESAMPLER, VIEWPORT, SCISSOR, + RASTER, CLEAR, + BINDPROGRAM, BINDTEXTURE, DRAW, DRAW_INDEXED, @@ -38,6 +43,19 @@ enum class GLRRenderCommand : uint8_t { struct GLRRenderData { GLRRenderCommand cmd; union { + struct { + GLboolean enabled; + GLenum srcColor; + GLenum dstColor; + GLenum srcAlpha; + GLenum dstAlpha; + GLenum funcColor; + GLenum funcAlpha; + int mask; + } blend; + struct { + float color[4]; + } blendColor; struct { GLboolean enabled; GLboolean write; @@ -45,14 +63,13 @@ struct GLRRenderData { } depth; struct { GLboolean enabled; - GLenum stencilOp; - GLenum stencilFunc; - uint8_t stencilWriteMask; - uint8_t stencilCompareMask; - uint8_t stencilRef; - GLenum stencilSFail; - GLenum stencilZFail; - GLenum stencilPass; + GLenum func; + uint8_t writeMask; + uint8_t compareMask; + uint8_t ref; + GLenum sFail; + GLenum zFail; + GLenum pass; } stencil; struct { GLenum mode; // primitive @@ -84,8 +101,11 @@ struct GLRRenderData { } clear; struct { int slot; - GLint texture; + GLRTexture *texture; } texture; + struct { + GLRProgram *program; + } program; struct { GLuint wrapU; GLuint wrapV; @@ -100,17 +120,10 @@ struct GLRRenderData { GLRect2D rc; } scissor; struct { - GLboolean enabled; - GLenum srcColor; - GLenum dstColor; - GLenum srcAlpha; - GLenum dstAlpha; - GLenum funcColor; - GLenum funcAlpha; - } blend; - struct { - float color[4]; - } blendColor; + GLboolean cullEnable; + GLenum frontFace; + GLenum cullFace; + } raster; }; }; @@ -130,6 +143,7 @@ enum class GLRInitStepType : uint8_t { class GLRShader; class GLRTexture; class GLRProgram; +class GLRBuffer; struct GLRInitStep { GLRInitStep(GLRInitStepType _type) : stepType(_type) {} @@ -143,13 +157,17 @@ struct GLRInitStep { } create_texture; struct { GLRShader *shader; - const char *code; + char *code; + GLuint stage; } create_shader; struct { GLRProgram *program; - GLRShader *vshader; - GLRShader *fshader; + GLRShader *shaders[3]; + int num_shaders; } create_program; + struct { + GLRBuffer *buffer; + } create_buffer; }; }; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 43bdaeaeb8..c44246c604 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -2,6 +2,7 @@ #include #include +#include #include "gfx/gl_common.h" #include "math/dataconv.h" @@ -74,7 +75,12 @@ public: glDeleteProgram(program); } } + struct Semantic { + int location; + const char *attrib; + }; GLuint program = 0; + std::vector semantics_; }; class GLRTexture { @@ -90,11 +96,11 @@ public: class GLRBuffer { public: ~GLRBuffer() { - if (texture) { - glDeleteTextures(1, &texture); + if (buffer) { + glDeleteBuffers(1, &buffer); } } - GLuint texture; + GLuint buffer; }; enum class GLRRunType { @@ -142,23 +148,35 @@ public: return step.create_texture.texture; } - GLRShader *CreateShader(const char *code) { + GLRShader *CreateShader(GLuint stage, std::string &code) { GLRInitStep step{ GLRInitStepType::CREATE_SHADER }; step.create_shader.shader = new GLRShader(); - step.create_shader.code = code; + step.create_shader.stage = stage; + step.create_shader.code = new char[code.size() + 1]; + memcpy(step.create_shader.code, code.data(), code.size() + 1); initSteps_.push_back(step); return step.create_shader.shader; } - GLRProgram *CreateProgram(GLRShader *vshader, GLRShader *fshader) { + GLRProgram *CreateProgram(std::vector shaders, std::vector semantics) { GLRInitStep step{ GLRInitStepType::CREATE_PROGRAM }; + assert(shaders.size() <= ARRAY_SIZE(step.create_program.shaders)); step.create_program.program = new GLRProgram(); - step.create_program.vshader = vshader; - step.create_program.fshader = fshader; + step.create_program.program->semantics_ = semantics; + for (int i = 0; i < shaders.size(); i++) { + step.create_program.shaders[i] = shaders[i]; + } initSteps_.push_back(step); return step.create_program.program; } + void DeleteShader(GLRShader *shader) { + deleter_.shaders.push_back(shader); + } + void DeleteProgram(GLRProgram *program) { + deleter_.programs.push_back(program); + } + void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil); GLuint BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment); bool CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride); @@ -167,6 +185,22 @@ public: void CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLOffset2D dstPos, int aspectMask); void BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLRect2D dstRect, int aspectMask, bool filter); + void BindProgram(GLRProgram *program) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::BINDPROGRAM }; + data.program.program = program; + curRenderStep_->commands.push_back(data); + } + + void SetDepth(bool enabled, bool write, GLenum func) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::DEPTH }; + data.depth.enabled = enabled; + data.depth.write = write; + data.depth.func = func; + curRenderStep_->commands.push_back(data); + } + void SetViewport(const GLRViewport &vp) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::VIEWPORT }; @@ -181,12 +215,16 @@ public: curRenderStep_->commands.push_back(data); } - void SetStencil(bool enabled, uint8_t writeMask, uint8_t compareMask, uint8_t refValue) { + void SetStencil(bool enabled, GLenum func, GLenum sFail, GLenum zFail, GLenum pass, uint8_t writeMask, uint8_t compareMask, uint8_t refValue) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::STENCIL }; - data.stencil.stencilWriteMask = writeMask; - data.stencil.stencilCompareMask = compareMask; - data.stencil.stencilRef = refValue; + data.stencil.func = func; + data.stencil.sFail = sFail; + data.stencil.zFail = zFail; + data.stencil.pass = pass; + data.stencil.writeMask = writeMask; + data.stencil.compareMask = compareMask; + data.stencil.ref = refValue; curRenderStep_->commands.push_back(data); } @@ -197,6 +235,15 @@ public: curRenderStep_->commands.push_back(data); } + void SetRaster(GLboolean cullEnable, GLenum frontFace, GLenum cullFace) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::RASTER }; + data.raster.cullEnable = cullEnable; + data.raster.frontFace = frontFace; + data.raster.cullFace = cullFace; + curRenderStep_->commands.push_back(data); + } + void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::CLEAR }; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index c2accb0479..6d1635723e 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -172,12 +172,10 @@ public: bool enabled; GLuint eqCol, eqAlpha; GLuint srcCol, srcAlpha, dstCol, dstAlpha; - bool logicEnabled; - GLuint logicOp; int colorMask; // uint32_t fixedColor; - void Apply() { + void Apply(GLRenderManager *render) { if (enabled) { glEnable(GL_BLEND); glBlendEquationSeparate(eqCol, eqAlpha); @@ -186,15 +184,6 @@ public: glDisable(GL_BLEND); } glColorMask(colorMask & 1, (colorMask >> 1) & 1, (colorMask >> 2) & 1, (colorMask >> 3) & 1); - -#if !defined(USING_GLES2) - if (logicEnabled) { - glEnable(GL_COLOR_LOGIC_OP); - glLogicOp(logicOp); - } else { - glDisable(GL_COLOR_LOGIC_OP); - } -#endif } }; @@ -223,36 +212,16 @@ public: uint8_t stencilCompareMask; uint8_t stencilWriteMask; - void Apply() { - if (depthTestEnabled) { - glEnable(GL_DEPTH_TEST); - glDepthFunc(depthComp); - glDepthMask(depthWriteEnabled); - } else { - glDisable(GL_DEPTH_TEST); - } - if (stencilEnabled) { - glEnable(GL_STENCIL_TEST); - glStencilOpSeparate(GL_FRONT_AND_BACK, stencilFail, stencilZFail, stencilPass); - glStencilFuncSeparate(GL_FRONT_AND_BACK, stencilCompareOp, stencilReference, stencilCompareMask); - glStencilMaskSeparate(GL_FRONT_AND_BACK, stencilWriteMask); - } else { - glDisable(GL_STENCIL_TEST); - } + void Apply(GLRenderManager *render) { + render->SetDepth(depthTestEnabled, depthWriteEnabled, depthComp); + render->SetStencil(stencilEnabled, stencilCompareOp, stencilFail, stencilZFail, stencilPass, stencilWriteMask, stencilCompareMask, stencilReference); } }; class OpenGLRasterState : public RasterState { public: - void Apply() { - glEnable(GL_SCISSOR_TEST); - if (!cullEnable) { - glDisable(GL_CULL_FACE); - return; - } - glEnable(GL_CULL_FACE); - glFrontFace(frontFace); - glCullFace(cullMode); + void Apply(GLRenderManager *render) { + render->SetRaster(cullEnable, frontFace, cullMode); } GLboolean cullEnable; @@ -277,17 +246,18 @@ GLuint ShaderStageToOpenGL(ShaderStage stage) { class OpenGLShaderModule : public ShaderModule { public: - OpenGLShaderModule(ShaderStage stage) : stage_(stage) { + OpenGLShaderModule(GLRenderManager *render, ShaderStage stage) : render_(render), stage_(stage) { + ILOG("Shader module created (%p)", this); glstage_ = ShaderStageToOpenGL(stage); } ~OpenGLShaderModule() { if (shader_) - glDeleteShader(shader_); + render_->DeleteShader(shader_); } - bool Compile(ShaderLanguage language, const uint8_t *data, size_t dataSize); - GLuint GetShader() const { + bool Compile(GLRenderManager *render, ShaderLanguage language, const uint8_t *data, size_t dataSize); + GLRShader *GetShader() const { return shader_; } const std::string &GetSource() const { return source_; } @@ -300,19 +270,17 @@ public: } private: + GLRenderManager *render_; ShaderStage stage_; ShaderLanguage language_; - GLuint shader_ = 0; + GLRShader *shader_ = nullptr; GLuint glstage_ = 0; bool ok_ = false; std::string source_; // So we can recompile in case of context loss. }; -bool OpenGLShaderModule::Compile(ShaderLanguage language, const uint8_t *data, size_t dataSize) { +bool OpenGLShaderModule::Compile(GLRenderManager *render, ShaderLanguage language, const uint8_t *data, size_t dataSize) { source_ = std::string((const char *)data); - shader_ = glCreateShader(glstage_); - language_ = language; - std::string temp; // Add the prelude on automatically. if (glstage_ == GL_FRAGMENT_SHADER || glstage_ == GL_VERTEX_SHADER) { @@ -320,23 +288,8 @@ bool OpenGLShaderModule::Compile(ShaderLanguage language, const uint8_t *data, s source_ = temp.c_str(); } - const char *code = source_.c_str(); - glShaderSource(shader_, 1, &code, nullptr); - glCompileShader(shader_); - GLint success = 0; - glGetShaderiv(shader_, GL_COMPILE_STATUS, &success); - if (!success) { -#define MAX_INFO_LOG_SIZE 2048 - GLchar infoLog[MAX_INFO_LOG_SIZE]; - GLsizei len = 0; - glGetShaderInfoLog(shader_, MAX_INFO_LOG_SIZE, &len, infoLog); - infoLog[len] = '\0'; - glDeleteShader(shader_); - shader_ = 0; - ILOG("%s Shader compile error:\n%s", glstage_ == GL_FRAGMENT_SHADER ? "Fragment" : "Vertex", infoLog); - } - ok_ = success != 0; - return ok_; + shader_ = render->CreateShader(glstage_, source_); + return true; } class OpenGLInputLayout : public InputLayout { @@ -365,14 +318,13 @@ struct UniformInfo { class OpenGLPipeline : public Pipeline { public: - OpenGLPipeline() { - program_ = 0; + OpenGLPipeline(GLRenderManager *render) : render_(render) { } ~OpenGLPipeline() { for (auto &iter : shaders) { iter->Release(); } - glDeleteProgram(program_); + render_->DeleteProgram(program_); if (depthStencil) depthStencil->Release(); if (blend) blend->Release(); if (raster) raster->Release(); @@ -397,8 +349,9 @@ public: // TODO: Optimize by getting the locations first and putting in a custom struct UniformBufferDesc dynamicUniforms; - GLuint program_; + GLRProgram *program_ = nullptr; private: + GLRenderManager *render_; std::map uniformCache_; }; @@ -976,10 +929,6 @@ BlendState *OpenGLContext::CreateBlendState(const BlendStateDesc &desc) { bs->eqAlpha = blendEqToGL[(int)desc.eqAlpha]; bs->srcAlpha = blendFactorToGL[(int)desc.srcAlpha]; bs->dstAlpha = blendFactorToGL[(int)desc.dstAlpha]; -#ifndef USING_GLES2 - bs->logicEnabled = desc.logicEnabled; - bs->logicOp = logicOpToGL[(int)desc.logicOp]; -#endif bs->colorMask = desc.colorMask; return bs; } @@ -1077,7 +1026,7 @@ Pipeline *OpenGLContext::CreateGraphicsPipeline(const PipelineDesc &desc) { ELOG("Pipeline requires at least one shader"); return NULL; } - OpenGLPipeline *pipeline = new OpenGLPipeline(); + OpenGLPipeline *pipeline = new OpenGLPipeline(&renderManager_); for (auto iter : desc.shaders) { iter->AddRef(); pipeline->shaders.push_back(static_cast(iter)); @@ -1149,8 +1098,8 @@ void OpenGLContext::ApplySamplers() { } ShaderModule *OpenGLContext::CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize) { - OpenGLShaderModule *shader = new OpenGLShaderModule(stage); - if (shader->Compile(language, data, dataSize)) { + OpenGLShaderModule *shader = new OpenGLShaderModule(&renderManager_, stage); + if (shader->Compile(&renderManager_, language, data, dataSize)) { return shader; } else { shader->Release(); @@ -1159,53 +1108,20 @@ ShaderModule *OpenGLContext::CreateShaderModule(ShaderStage stage, ShaderLanguag } bool OpenGLPipeline::LinkShaders() { - program_ = glCreateProgram(); + std::vector linkShaders; for (auto iter : shaders) { - glAttachShader(program_, iter->GetShader()); + linkShaders.push_back(iter->GetShader()); } - + std::vector semantics; + semantics.push_back({ SEM_POSITION, "Position" }); // Bind all the common vertex data points. Mismatching ones will be ignored. - glBindAttribLocation(program_, SEM_POSITION, "Position"); - glBindAttribLocation(program_, SEM_COLOR0, "Color0"); - glBindAttribLocation(program_, SEM_TEXCOORD0, "TexCoord0"); - glBindAttribLocation(program_, SEM_NORMAL, "Normal"); - glBindAttribLocation(program_, SEM_TANGENT, "Tangent"); - glBindAttribLocation(program_, SEM_BINORMAL, "Binormal"); - glLinkProgram(program_); - - GLint linkStatus = GL_FALSE; - glGetProgramiv(program_, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) { - GLint bufLength = 0; - glGetProgramiv(program_, GL_INFO_LOG_LENGTH, &bufLength); - if (bufLength) { - char* buf = new char[bufLength]; - glGetProgramInfoLog(program_, bufLength, NULL, buf); - ELOG("Could not link program:\n %s", buf); - // We've thrown out the source at this point. Might want to do something about that. -#ifdef _WIN32 - OutputDebugStringUTF8(buf); -#endif - delete[] buf; - } else { - ELOG("Could not link program with %d shaders for unknown reason:", (int)shaders.size()); - } - return false; - } - - // Auto-initialize samplers. - glUseProgram(program_); - for (int i = 0; i < 4; i++) { - char temp[256]; - sprintf(temp, "Sampler%i", i); - int samplerLoc = GetUniformLoc(temp); - if (samplerLoc != -1) { - glUniform1i(samplerLoc, i); - } - } - - // Here we could (using glGetAttribLocation) save a bitmask about which pieces of vertex data are used in the shader - // and then AND it with the vertex format bitmask later... + semantics.push_back({ SEM_POSITION, "Position" }); + semantics.push_back({ SEM_COLOR0, "Color0" }); + semantics.push_back({ SEM_TEXCOORD0, "TexCoord0" }); + semantics.push_back({ SEM_NORMAL, "Normal" }); + semantics.push_back({ SEM_TANGENT, "Tangent" }); + semantics.push_back({ SEM_BINORMAL, "Binormal" }); + program_ = render_->CreateProgram(linkShaders, semantics); return true; } @@ -1215,7 +1131,8 @@ int OpenGLPipeline::GetUniformLoc(const char *name) { if (iter != uniformCache_.end()) { loc = iter->second.loc_; } else { - loc = glGetUniformLocation(program_, name); + Crash(); + // loc = glGetUniformLocation(program_, name); UniformInfo info; info.loc_ = loc; uniformCache_[name] = info; @@ -1225,10 +1142,10 @@ int OpenGLPipeline::GetUniformLoc(const char *name) { void OpenGLContext::BindPipeline(Pipeline *pipeline) { curPipeline_ = (OpenGLPipeline *)pipeline; - curPipeline_->blend->Apply(); - curPipeline_->depthStencil->Apply(); - curPipeline_->raster->Apply(); - glUseProgram(curPipeline_->program_); + curPipeline_->blend->Apply(&renderManager_); + curPipeline_->depthStencil->Apply(&renderManager_); + curPipeline_->raster->Apply(&renderManager_); + renderManager_.BindProgram(curPipeline_->program_); } void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) { From 9babdb712c5f9a1e34a5bbffdc6c0e5511d66915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Nov 2017 20:17:17 +0100 Subject: [PATCH 003/291] More gl-render-manager --- ext/native/thin3d/GLQueueRunner.cpp | 86 +++++++++--- ext/native/thin3d/GLQueueRunner.h | 32 ++++- ext/native/thin3d/GLRenderManager.h | 127 ++++++++++++++++- ext/native/thin3d/thin3d.h | 5 +- ext/native/thin3d/thin3d_gl.cpp | 203 +++++++++------------------- 5 files changed, 290 insertions(+), 163 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index bdea224380..3d2167377f 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -2,6 +2,7 @@ #include "GLRenderManager.h" #include "base/logging.h" #include "gfx/gl_common.h" +#include "gfx/gl_debug_log.h" #include "gfx_es2/gpu_features.h" #include "math/dataconv.h" @@ -19,6 +20,21 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { switch (step.stepType) { case GLRInitStepType::CREATE_TEXTURE: break; + case GLRInitStepType::CREATE_BUFFER: + { + GLRBuffer *buffer = step.create_buffer.buffer; + glGenBuffers(1, &buffer->buffer); + glBindBuffer(buffer->target_, buffer->buffer); + glBufferData(buffer->target_, step.create_buffer.size, nullptr, step.create_buffer.usage); + break; + } + case GLRInitStepType::BUFFER_SUBDATA: + { + GLRBuffer *buffer = step.buffer_subdata.buffer; + glBufferSubData(buffer->buffer, step.buffer_subdata.offset, step.buffer_subdata.size, step.buffer_subdata.data); + delete[] step.buffer_subdata.data; + break; + } case GLRInitStepType::CREATE_PROGRAM: { GLRProgram *program = step.create_program.program; @@ -90,12 +106,18 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { } break; } - case GLRInitStepType::CREATE_BUFFER: - glGenBuffers(1, &step.create_buffer.buffer->buffer); - break; case GLRInitStepType::TEXTURE_SUBDATA: break; + case GLRInitStepType::TEXTURE_IMAGE: + { + GLRTexture *tex = step.texture_image.texture; + CHECK_GL_ERROR_IF_DEBUG(); + glTexImage2D(tex->target, step.texture_image.level, step.texture_image.internalFormat, step.texture_image.width, step.texture_image.height, 0, step.texture_image.format, step.texture_image.type, step.texture_image.data); + delete[] step.texture_image.data; + CHECK_GL_ERROR_IF_DEBUG(); + break; + } } } } @@ -148,7 +170,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { int curHeight = step.render.framebuffer ? step.render.framebuffer->height : 0; // vulkan_->GetBackbufferHeight(); GLRFramebuffer *fb = step.render.framebuffer; - + GLRProgram *curProgram = nullptr; GLint activeTexture = GL_TEXTURE0; auto &commands = step.commands; @@ -197,24 +219,40 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glScissor(c.scissor.rc.x, c.scissor.rc.y, c.scissor.rc.w, c.scissor.rc.h); break; case GLRRenderCommand::UNIFORM4F: - switch (c.uniform4.count) { - case 1: - glUniform1f(c.uniform4.loc, c.uniform4.v[0]); - break; - case 2: - glUniform2fv(c.uniform4.loc, 1, c.uniform4.v); - break; - case 3: - glUniform3fv(c.uniform4.loc, 1, c.uniform4.v); - break; - case 4: - glUniform4fv(c.uniform4.loc, 1, c.uniform4.v); - break; + { + int loc = c.uniform4.loc; + if (c.uniform4.name) { + loc = curProgram->GetUniformLoc(c.uniform4.name); + } + if (loc >= 0) { + switch (c.uniform4.count) { + case 1: + glUniform1f(loc, c.uniform4.v[0]); + break; + case 2: + glUniform2fv(loc, 1, c.uniform4.v); + break; + case 3: + glUniform3fv(loc, 1, c.uniform4.v); + break; + case 4: + glUniform4fv(loc, 1, c.uniform4.v); + break; + } } break; + } case GLRRenderCommand::UNIFORMMATRIX: - glUniformMatrix4fv(c.uniformMatrix4.loc, 1, false, c.uniformMatrix4.m); + { + int loc = c.uniform4.loc; + if (c.uniform4.name) { + loc = curProgram->GetUniformLoc(c.uniform4.name); + } + if (loc >= 0) { + glUniformMatrix4fv(loc, 1, false, c.uniformMatrix4.m); + } break; + } case GLRRenderCommand::STENCIL: glStencilFunc(c.stencil.func, c.stencil.ref, c.stencil.compareMask); glStencilOp(c.stencil.sFail, c.stencil.zFail, c.stencil.pass); @@ -227,14 +265,18 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glActiveTexture(target); activeTexture = target; } - glBindTexture(GL_TEXTURE_2D, c.texture.texture->texture); + glBindTexture(c.texture.texture->target, c.texture.texture->texture); break; } case GLRRenderCommand::BINDPROGRAM: { glUseProgram(c.program.program->program); + curProgram = c.program.program; break; } + case GLRRenderCommand::GENMIPS: + glGenerateMipmap(GL_TEXTURE_2D); + break; case GLRRenderCommand::DRAW: glDrawArrays(c.draw.mode, c.draw.first, c.draw.count); break; @@ -243,6 +285,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glDrawElements(c.drawIndexed.mode, c.drawIndexed.count, c.drawIndexed.indexType, c.drawIndexed.indices); } break; + case GLRRenderCommand::TEXTURESAMPLER: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter); + break; } } if (activeTexture != GL_TEXTURE0) diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index e16ada4562..e953e840a7 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -35,6 +35,7 @@ enum class GLRRenderCommand : uint8_t { CLEAR, BINDPROGRAM, BINDTEXTURE, + GENMIPS, DRAW, DRAW_INDEXED, PUSH_CONSTANTS, @@ -85,11 +86,13 @@ struct GLRRenderData { void *indices; } drawIndexed; struct { + const char *name; // if null, use loc GLint loc; GLint count; float v[4]; } uniform4; struct { + const char *name; // if null, use loc GLint loc; float m[16]; } uniformMatrix4; @@ -107,11 +110,10 @@ struct GLRRenderData { GLRProgram *program; } program; struct { - GLuint wrapU; - GLuint wrapV; - bool maxFilter; - bool minFilter; - bool mipFilter; + GLenum wrapS; + GLenum wrapT; + GLenum magFilter; + GLenum minFilter; // also includes mip. GL... } textureSampler; struct { GLRViewport vp; @@ -136,6 +138,7 @@ enum class GLRInitStepType : uint8_t { CREATE_PROGRAM, CREATE_BUFFER, + TEXTURE_IMAGE, TEXTURE_SUBDATA, BUFFER_SUBDATA, }; @@ -151,6 +154,7 @@ struct GLRInitStep { union { struct { GLRTexture *texture; + GLenum target; int width; int height; // ... @@ -167,7 +171,25 @@ struct GLRInitStep { } create_program; struct { GLRBuffer *buffer; + int size; + GLuint usage; } create_buffer; + struct { + GLRBuffer *buffer; + int offset; + int size; + uint8_t *data; // owned, delete[]-d + } buffer_subdata; + struct { + GLRTexture *texture; + GLenum internalFormat; + GLenum format; + GLenum type; + int level; + int width; + int height; + uint8_t *data; // owned, delete[]-d + } texture_image; }; }; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index c44246c604..a48103b539 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include #include @@ -81,6 +83,26 @@ public: }; GLuint program = 0; std::vector semantics_; + + struct UniformInfo { + int loc_; + }; + + // Must ONLY be called from GLQueueRunner! + int GetUniformLoc(const char *name) { + auto iter = uniformCache_.find(name); + int loc = -1; + if (iter != uniformCache_.end()) { + loc = iter->second.loc_; + } else { + loc = glGetUniformLocation(program, name); + UniformInfo info; + info.loc_ = loc; + uniformCache_[name] = info; + } + return loc; + } + std::map uniformCache_; }; class GLRTexture { @@ -91,16 +113,20 @@ public: } } GLuint texture; + GLenum target; }; class GLRBuffer { public: + GLRBuffer(GLuint target) : target_(target) {} ~GLRBuffer() { if (buffer) { glDeleteBuffers(1, &buffer); } } GLuint buffer; + GLuint target_; +private: }; enum class GLRRunType { @@ -119,6 +145,8 @@ public: std::vector shaders; std::vector programs; + std::vector buffers; + std::vector textures; }; @@ -139,15 +167,23 @@ public: void Wipe(); // Creation commands. These were not needed in Vulkan since there we can do that on the main thread. - GLRTexture *CreateTexture(int w, int h) { + GLRTexture *CreateTexture(GLenum target, int w, int h) { GLRInitStep step{ GLRInitStepType::CREATE_TEXTURE }; step.create_texture.texture = new GLRTexture(); + step.create_texture.texture->target = target; step.create_texture.width = w; step.create_texture.height = h; initSteps_.push_back(step); return step.create_texture.texture; } + GLRBuffer *CreateBuffer(GLuint target, int size, GLuint usage) { + GLRInitStep step{ GLRInitStepType::CREATE_BUFFER }; + step.create_buffer.buffer = new GLRBuffer(target); + initSteps_.push_back(step); + return step.create_buffer.buffer; + } + GLRShader *CreateShader(GLuint stage, std::string &code) { GLRInitStep step{ GLRInitStepType::CREATE_SHADER }; step.create_shader.shader = new GLRShader(); @@ -176,6 +212,12 @@ public: void DeleteProgram(GLRProgram *program) { deleter_.programs.push_back(program); } + void DeleteBuffer(GLRBuffer *buffer) { + deleter_.buffers.push_back(buffer); + } + void DeleteTexture(GLRTexture *texture) { + deleter_.textures.push_back(texture); + } void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil); GLuint BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment); @@ -185,6 +227,38 @@ public: void CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLOffset2D dstPos, int aspectMask); void BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLRect2D dstRect, int aspectMask, bool filter); + // Takes ownership of data. + void BufferSubdata(GLRBuffer *buffer, int offset, int size, uint8_t *data) { + // TODO: Maybe should be a render command instead of an init command? When possible it's better as + // an init command, that's for sure. + GLRInitStep step{ GLRInitStepType::BUFFER_SUBDATA }; + step.buffer_subdata.buffer = buffer; + step.buffer_subdata.offset = offset; + step.buffer_subdata.size = size; + step.buffer_subdata.data = data; + initSteps_.push_back(step); + } + + void TextureImage(GLRTexture *texture, int level, int width, int height, GLenum internalFormat, GLenum format, GLenum type, uint8_t *data) { + GLRInitStep step{ GLRInitStepType::TEXTURE_IMAGE }; + step.texture_image.data = data; + step.texture_image.internalFormat = internalFormat; + step.texture_image.format = format; + step.texture_image.type = type; + step.texture_image.level = level; + step.texture_image.width = width; + step.texture_image.height = height; + initSteps_.push_back(step); + } + + void BindTexture(int slot, GLRTexture *tex) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::BINDTEXTURE }; + data.texture.slot = slot; + data.texture.texture = tex; + curRenderStep_->commands.push_back(data); + } + void BindProgram(GLRProgram *program) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::BINDPROGRAM }; @@ -192,6 +266,12 @@ public: curRenderStep_->commands.push_back(data); } + void GenerateMipmap() { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::GENMIPS }; + curRenderStep_->commands.push_back(data); + } + void SetDepth(bool enabled, bool write, GLenum func) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::DEPTH }; @@ -215,6 +295,40 @@ public: curRenderStep_->commands.push_back(data); } + void SetUniformF(int loc, int count, const float *udata) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; + data.uniform4.loc = loc; + data.uniform4.count = count; + memcpy(data.uniform4.v, udata, sizeof(float) * count); + curRenderStep_->commands.push_back(data); + } + + void SetUniformF(const char *name, int count, const float *udata) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; + data.uniform4.name = name; + data.uniform4.count = count; + memcpy(data.uniform4.v, udata, sizeof(float) * count); + curRenderStep_->commands.push_back(data); + } + + void SetUniformM4x4(int loc, const float *udata) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; + data.uniformMatrix4.loc = loc; + memcpy(data.uniformMatrix4.m, udata, sizeof(float) * 16); + curRenderStep_->commands.push_back(data); + } + + void SetUniformM4x4(const char *name, const float *udata) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; + data.uniformMatrix4.name = name; + memcpy(data.uniformMatrix4.m, udata, sizeof(float) * 16); + curRenderStep_->commands.push_back(data); + } + void SetStencil(bool enabled, GLenum func, GLenum sFail, GLenum zFail, GLenum pass, uint8_t writeMask, uint8_t compareMask, uint8_t refValue) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::STENCIL }; @@ -243,6 +357,17 @@ public: data.raster.cullFace = cullFace; curRenderStep_->commands.push_back(data); } + + // Modifies the current texture as per GL specs, not global state. + void SetTextureSampler(GLenum wrapS, GLenum wrapT, GLenum magFilter, GLenum minFilter) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::TEXTURESAMPLER }; + data.textureSampler.wrapS = wrapS; + data.textureSampler.wrapT = wrapT; + data.textureSampler.magFilter = magFilter; + data.textureSampler.minFilter = minFilter; + curRenderStep_->commands.push_back(data); + } void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index b401a6268f..6bbc0d50e8 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -587,7 +587,10 @@ public: // color must be 0, for now. virtual void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) = 0; - virtual uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) = 0; + // deprecated + virtual uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) { + return 0; + } virtual void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) = 0; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 6d1635723e..b247ca0b96 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -312,10 +312,6 @@ public: intptr_t lastBase_; }; -struct UniformInfo { - int loc_; -}; - class OpenGLPipeline : public Pipeline { public: OpenGLPipeline(GLRenderManager *render) : render_(render) { @@ -352,7 +348,6 @@ public: GLRProgram *program_ = nullptr; private: GLRenderManager *render_; - std::map uniformCache_; }; class OpenGLFramebuffer; @@ -398,8 +393,6 @@ public: // color must be 0, for now. void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; - uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) override; - void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override; void BindSamplerStates(int start, int count, SamplerState **states) override { @@ -422,17 +415,12 @@ public: } void SetViewports(int count, Viewport *viewports) override { - // TODO: Use glViewportArrayv. - glViewport((GLint)viewports[0].TopLeftX, (GLint)viewports[0].TopLeftY, (GLsizei)viewports[0].Width, (GLsizei)viewports[0].Height); -#if defined(USING_GLES2) - glDepthRangef(viewports[0].MinDepth, viewports[0].MaxDepth); -#else - glDepthRange(viewports[0].MinDepth, viewports[0].MaxDepth); -#endif + // Same structure, different name. + renderManager_.SetViewport((GLRViewport &)*viewports); } void SetBlendFactor(float color[4]) override { - glBlendColor(color[0], color[1], color[2], color[3]); + renderManager_.SetBlendFactor(color); } void BindTextures(int start, int count, Texture **textures) override; @@ -585,7 +573,7 @@ inline bool isPowerOf2(int n) { class OpenGLTexture : public Texture { public: - OpenGLTexture(const TextureDesc &desc); + OpenGLTexture(GLRenderManager *render, const TextureDesc &desc); ~OpenGLTexture(); bool HasMips() const { @@ -595,8 +583,8 @@ public: return canWrap_; } TextureType GetType() const { return type_; } - void Bind() { - glBindTexture(target_, tex_); + void Bind(int stage) { + render_->BindTexture(stage, tex_); } void AutoGenMipmaps(); @@ -604,8 +592,8 @@ public: private: void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data); - GLuint tex_ = 0; - GLuint target_ = 0; + GLRenderManager *render_; + GLRTexture *tex_; DataFormat format_; TextureType type_; @@ -614,7 +602,7 @@ private: bool canWrap_; }; -OpenGLTexture::OpenGLTexture(const TextureDesc &desc) { +OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : render_(render) { generatedMips_ = false; canWrap_ = true; width_ = desc.width; @@ -622,16 +610,16 @@ OpenGLTexture::OpenGLTexture(const TextureDesc &desc) { depth_ = desc.depth; format_ = desc.format; type_ = desc.type; - target_ = TypeToTarget(desc.type); + GLenum target = TypeToTarget(desc.type); + tex_ = render->CreateTexture(target, width_, height_); + + render->BindTexture(0, tex_); + canWrap_ = isPowerOf2(width_) && isPowerOf2(height_); mipLevels_ = desc.mipLevels; if (!desc.initData.size()) return; - glActiveTexture(GL_TEXTURE0 + 0); - glGenTextures(1, &tex_); - glBindTexture(target_, tex_); - int level = 0; for (auto data : desc.initData) { SetImageData(0, 0, 0, width_, height_, depth_, level, 0, data); @@ -641,6 +629,8 @@ OpenGLTexture::OpenGLTexture(const TextureDesc &desc) { } mipLevels_ = desc.generateMips ? desc.mipLevels : level; + render->SetTextureSampler(GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_LINEAR, mipLevels_ > 1 ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); + /* #ifdef USING_GLES2 if (gl_extensions.GLES3) { glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, mipLevels_ - 1); @@ -648,8 +638,7 @@ OpenGLTexture::OpenGLTexture(const TextureDesc &desc) { #else glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, mipLevels_ - 1); #endif - glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, mipLevels_ > 1 ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); - glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +*/ if ((int)desc.initData.size() < desc.mipLevels && desc.generateMips) { ILOG("Generating mipmaps"); @@ -657,12 +646,12 @@ OpenGLTexture::OpenGLTexture(const TextureDesc &desc) { } // Unbind. - glBindTexture(target_, 0); + render->BindTexture(0, nullptr); } OpenGLTexture::~OpenGLTexture() { if (tex_) { - glDeleteTextures(1, &tex_); + render_->DeleteTexture(tex_); tex_ = 0; generatedMips_ = false; } @@ -670,8 +659,8 @@ OpenGLTexture::~OpenGLTexture() { void OpenGLTexture::AutoGenMipmaps() { if (!generatedMips_) { - glBindTexture(target_, tex_); - glGenerateMipmap(target_); + render_->BindTexture(0, tex_); + render_->GenerateMipmap(); generatedMips_ = true; } } @@ -681,6 +670,8 @@ public: OpenGLFramebuffer() {} ~OpenGLFramebuffer(); + GLRFramebuffer *framebuffer; + GLuint handle = 0; GLuint color_texture = 0; GLuint z_stencil_buffer = 0; // Either this is set, or the two below. @@ -792,16 +783,12 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int return; } - CHECK_GL_ERROR_IF_DEBUG(); - switch (target_) { - case GL_TEXTURE_2D: - glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width_, height_, 0, format, type, data); - break; - default: - ELOG("Thin3D GL: Targets other than GL_TEXTURE_2D not yet supported"); - break; + // Make a copy of data with stride eliminated. + uint8_t *texData = new uint8_t[width * height * alignment]; + for (int y = 0; y < height; y++) { + memcpy(texData + y * width * alignment, data + y * stride * alignment, width * alignment); } - CHECK_GL_ERROR_IF_DEBUG(); + render_->TextureImage(tex_, level, width, height, internalFormat, format, type, texData); } @@ -879,7 +866,7 @@ bool OpenGLContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBit Texture *OpenGLContext::CreateTexture(const TextureDesc &desc) { - return new OpenGLTexture(desc); + return new OpenGLTexture(&renderManager_, desc); } OpenGLInputLayout::~OpenGLInputLayout() { @@ -978,28 +965,29 @@ RasterState *OpenGLContext::CreateRasterState(const RasterStateDesc &desc) { class OpenGLBuffer : public Buffer { public: - OpenGLBuffer(size_t size, uint32_t flags) { - glGenBuffers(1, &buffer_); + OpenGLBuffer(GLRenderManager *render, size_t size, uint32_t flags) : render_(render) { target_ = (flags & BufferUsageFlag::INDEXDATA) ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER; usage_ = 0; if (flags & BufferUsageFlag::DYNAMIC) usage_ = GL_STREAM_DRAW; else usage_ = GL_STATIC_DRAW; + buffer_ = render->CreateBuffer(target_, size, usage_); totalSize_ = size; - glBindBuffer(target_, buffer_); - glBufferData(target_, size, NULL, usage_); } ~OpenGLBuffer() override { - glDeleteBuffers(1, &buffer_); + render_->DeleteBuffer(buffer_); } void Bind(int offset) { + Crash(); + // render_->BindBuffer(buffer_); // TODO: Can't support offset using ES 2.0 - glBindBuffer(target_, buffer_); + // glBindBuffer(target_, buffer_); } - GLuint buffer_; + GLRenderManager *render_; + GLRBuffer *buffer_; GLuint target_; GLuint usage_; @@ -1007,7 +995,7 @@ public: }; Buffer *OpenGLContext::CreateBuffer(size_t size, uint32_t usageFlags) { - return new OpenGLBuffer(size, usageFlags); + return new OpenGLBuffer(&renderManager_, size, usageFlags); } void OpenGLContext::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) { @@ -1017,14 +1005,17 @@ void OpenGLContext::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t off if (size + offset > buf->totalSize_) { Crash(); } + + uint8_t *dataCopy = new uint8_t[size]; + memcpy(dataCopy, data, size); // if (flags & UPDATE_DISCARD) we could try to orphan the buffer using glBufferData. - glBufferSubData(buf->target_, offset, size, data); + renderManager_.BufferSubdata(buf->buffer_, offset, size, dataCopy); } Pipeline *OpenGLContext::CreateGraphicsPipeline(const PipelineDesc &desc) { if (!desc.shaders.size()) { ELOG("Pipeline requires at least one shader"); - return NULL; + return nullptr; } OpenGLPipeline *pipeline = new OpenGLPipeline(&renderManager_); for (auto iter : desc.shaders) { @@ -1056,16 +1047,14 @@ void OpenGLContext::BindTextures(int start, int count, Texture **textures) { maxTextures_ = std::max(maxTextures_, start + count); for (int i = start; i < start + count; i++) { OpenGLTexture *glTex = static_cast(textures[i]); - glActiveTexture(GL_TEXTURE0 + i); if (!glTex) { boundTextures_[i] = 0; - glBindTexture(GL_TEXTURE_2D, 0); + renderManager_.BindTexture(i, nullptr); continue; } - glTex->Bind(); + glTex->Bind(i); boundTextures_[i] = glTex; } - glActiveTexture(GL_TEXTURE0); } void OpenGLContext::ApplySamplers() { @@ -1075,24 +1064,18 @@ void OpenGLContext::ApplySamplers() { const OpenGLTexture *tex = boundTextures_[i]; if (!tex) continue; + GLenum wrapS; + GLenum wrapT; if (tex->CanWrap()) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, samp->wrapU); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, samp->wrapV); -#ifndef USING_GLES2 - if (tex->GetType() == TextureType::LINEAR3D) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, samp->wrapW); -#endif + wrapS = samp->wrapU; + wrapT = samp->wrapV; } else { - 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, samp->magFilt); - if (tex->HasMips()) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, samp->mipMinFilt); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, samp->minFilt); + wrapS = GL_CLAMP_TO_EDGE; + wrapT = GL_CLAMP_TO_EDGE; } + GLenum magFilt = samp->magFilt; + GLenum minFilt = tex->HasMips() ? samp->mipMinFilt : samp->minFilt; + renderManager_.SetTextureSampler(wrapS, wrapT, magFilt, minFilt); } } } @@ -1113,7 +1096,6 @@ bool OpenGLPipeline::LinkShaders() { linkShaders.push_back(iter->GetShader()); } std::vector semantics; - semantics.push_back({ SEM_POSITION, "Position" }); // Bind all the common vertex data points. Mismatching ones will be ignored. semantics.push_back({ SEM_POSITION, "Position" }); semantics.push_back({ SEM_COLOR0, "Color0" }); @@ -1125,21 +1107,6 @@ bool OpenGLPipeline::LinkShaders() { return true; } -int OpenGLPipeline::GetUniformLoc(const char *name) { - auto iter = uniformCache_.find(name); - int loc = -1; - if (iter != uniformCache_.end()) { - loc = iter->second.loc_; - } else { - Crash(); - // loc = glGetUniformLocation(program_, name); - UniformInfo info; - info.loc_ = loc; - uniformCache_[name] = info; - } - return loc; -} - void OpenGLContext::BindPipeline(Pipeline *pipeline) { curPipeline_ = (OpenGLPipeline *)pipeline; curPipeline_->blend->Apply(&renderManager_); @@ -1154,16 +1121,13 @@ void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) { } for (auto &uniform : curPipeline_->dynamicUniforms.uniforms) { - GLuint loc = curPipeline_->GetUniformLoc(uniform.name); - if (loc == -1) - Crash(); const float *data = (const float *)((uint8_t *)ub + uniform.offset); switch (uniform.type) { case UniformType::FLOAT4: - glUniform1fv(loc, 4, data); + renderManager_.SetUniformF(uniform.name, 4, data); break; case UniformType::MATRIX4X4: - glUniformMatrix4fv(loc, 1, false, data); + renderManager_.SetUniformM4x4(uniform.name, data); break; } } @@ -1612,42 +1576,17 @@ void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const Render void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) { OpenGLFramebuffer *src = (OpenGLFramebuffer *)fbsrc; OpenGLFramebuffer *dst = (OpenGLFramebuffer *)fbdst; - GLuint srcTex = 0; - GLuint dstTex = 0; - GLuint target = GL_TEXTURE_2D; - switch (channelBits) { - case FB_COLOR_BIT: - srcTex = src->color_texture; - dstTex = dst->color_texture; - break; - case FB_DEPTH_BIT: - target = GL_RENDERBUFFER; - srcTex = src->z_buffer ? src->z_buffer : src->z_stencil_buffer; - dstTex = dst->z_buffer ? dst->z_buffer : dst->z_stencil_buffer; - break; + + int aspect = 0; + if (channelBits & FB_COLOR_BIT) { + aspect |= GLR_ASPECT_COLOR; + } else if (channelBits & (FB_STENCIL_BIT | FB_DEPTH_BIT)) { + if (channelBits & FB_STENCIL_BIT) + aspect |= GLR_ASPECT_STENCIL; + if (channelBits & FB_DEPTH_BIT) + aspect |= GLR_ASPECT_DEPTH; } -#if defined(USING_GLES2) -#ifndef IOS - glCopyImageSubDataOES( - srcTex, target, srcLevel, srcX, srcY, srcZ, - dstTex, target, dstLevel, dstX, dstY, dstZ, - width, height, depth); -#endif -#else - if (gl_extensions.ARB_copy_image) { - glCopyImageSubData( - srcTex, target, srcLevel, srcX, srcY, srcZ, - dstTex, target, dstLevel, dstX, dstY, dstZ, - width, height, depth); - } else if (gl_extensions.NV_copy_image) { - // Older, pre GL 4.x NVIDIA cards. - glCopyImageSubDataNV( - srcTex, target, srcLevel, srcX, srcY, srcZ, - dstTex, target, dstLevel, dstX, dstY, dstZ, - width, height, depth); - } -#endif - CHECK_GL_ERROR_IF_DEBUG(); + renderManager_.CopyFramebuffer(src->framebuffer, GLRect2D{ srcX, srcY, width, height }, dst->framebuffer, GLOffset2D{ dstX, dstY }, aspect); } bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *fbdst, int dstX1, int dstY1, int dstX2, int dstY2, int channels, FBBlitFilter linearFilter) { @@ -1679,16 +1618,6 @@ bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, in } } -uintptr_t OpenGLContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) { - OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; - switch (channelBits) { - case FB_COLOR_BIT: return (uintptr_t)fb->color_texture; - case FB_DEPTH_BIT: return (uintptr_t)(fb->z_buffer ? fb->z_buffer : fb->z_stencil_buffer); - default: - return 0; - } -} - void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int color) { OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; if (!fb) From b8e4ae08a7bf7b808e7113050070f1aa6f223c63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Nov 2017 21:12:11 +0100 Subject: [PATCH 004/291] Even more gl-render-manager --- ext/native/thin3d/GLQueueRunner.cpp | 46 ++++++- ext/native/thin3d/GLQueueRunner.h | 21 +++- ext/native/thin3d/GLRenderManager.cpp | 9 +- ext/native/thin3d/GLRenderManager.h | 45 +++++++ ext/native/thin3d/thin3d_gl.cpp | 175 +++++++++++--------------- 5 files changed, 179 insertions(+), 117 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 3d2167377f..f5275fdc72 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -107,6 +107,12 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { break; } + case GLRInitStepType::CREATE_INPUT_LAYOUT: + { + GLRInputLayout *layout = step.create_input_layout.inputLayout; + // TODO + break; + } case GLRInitStepType::TEXTURE_SUBDATA: break; case GLRInitStepType::TEXTURE_IMAGE: @@ -195,17 +201,22 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } break; case GLRRenderCommand::CLEAR: - if (c.clear.clearMask & GLR_ASPECT_COLOR) { + if (c.clear.clearMask & GL_COLOR_BUFFER_BIT) { float color[4]; Uint8x4ToFloat4(color, c.clear.clearColor); glClearColor(color[0], color[1], color[2], color[3]); } - if (c.clear.clearMask & GLR_ASPECT_DEPTH) { + if (c.clear.clearMask & GL_DEPTH_BUFFER_BIT) { +#if defined(USING_GLES2) + glClearDepthf(c.clear.clearZ); +#else glClearDepth(c.clear.clearZ); +#endif } - if (c.clear.clearMask & GLR_ASPECT_STENCIL) { + if (c.clear.clearMask & GL_STENCIL) { glClearStencil(c.clear.clearStencil); } + glClear(c.clear.clearMask); break; case GLRRenderCommand::BLENDCOLOR: glBlendColor(c.blendColor.color[0], c.blendColor.color[1], c.blendColor.color[2], c.blendColor.color[3]); @@ -274,6 +285,29 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { curProgram = c.program.program; break; } + case GLRRenderCommand::BIND_INPUT_LAYOUT: + { + GLRInputLayout *layout = c.inputLayout.inputLayout; + for (int i = 0; i < 7; i++) { // SEM_MAX + if (layout->semanticsMask_ & (1 << i)) { + glEnableVertexAttribArray(i); + } + } + for (auto &entry: layout->entries) { + glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.inputLayout.offset + entry.offset)); + } + break; + } + case GLRRenderCommand::UNBIND_INPUT_LAYOUT: + { + GLRInputLayout *layout = c.inputLayout.inputLayout; + for (int i = 0; i < 7; i++) { // SEM_MAX + if (layout->semanticsMask_ & (1 << i)) { + glDisableVertexAttribArray(i); + } + } + break; + } case GLRRenderCommand::GENMIPS: glGenerateMipmap(GL_TEXTURE_2D); break; @@ -295,6 +329,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } if (activeTexture != GL_TEXTURE0) glActiveTexture(GL_TEXTURE0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } void GLQueueRunner::PerformCopy(const GLRStep &step) { @@ -315,11 +351,11 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) { int depth = 1; switch (step.copy.aspectMask) { - case GLR_ASPECT_COLOR: + case GL_COLOR_BUFFER_BIT: srcTex = src->color.texture; dstTex = dst->color.texture; break; - case GLR_ASPECT_DEPTH: + case GL_DEPTH_BUFFER_BIT: target = GL_RENDERBUFFER; srcTex = src->depth.texture; dstTex = src->depth.texture; diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index e953e840a7..ff8be97b6b 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -18,8 +18,12 @@ struct GLOffset2D { int x, y; }; -class GLRProgram; + +class GLRShader; class GLRTexture; +class GLRBuffer; +class GLRProgram; +class GLRInputLayout; enum class GLRRenderCommand : uint8_t { DEPTH, @@ -35,6 +39,8 @@ enum class GLRRenderCommand : uint8_t { CLEAR, BINDPROGRAM, BINDTEXTURE, + BIND_INPUT_LAYOUT, + UNBIND_INPUT_LAYOUT, GENMIPS, DRAW, DRAW_INDEXED, @@ -109,6 +115,10 @@ struct GLRRenderData { struct { GLRProgram *program; } program; + struct { + GLRInputLayout *inputLayout; + intptr_t offset; + } inputLayout; struct { GLenum wrapS; GLenum wrapT; @@ -137,17 +147,13 @@ enum class GLRInitStepType : uint8_t { CREATE_SHADER, CREATE_PROGRAM, CREATE_BUFFER, + CREATE_INPUT_LAYOUT, TEXTURE_IMAGE, TEXTURE_SUBDATA, BUFFER_SUBDATA, }; -class GLRShader; -class GLRTexture; -class GLRProgram; -class GLRBuffer; - struct GLRInitStep { GLRInitStep(GLRInitStepType _type) : stepType(_type) {} GLRInitStepType stepType; @@ -174,6 +180,9 @@ struct GLRInitStep { int size; GLuint usage; } create_buffer; + struct { + GLRInputLayout *inputLayout; + } create_input_layout; struct { GLRBuffer *buffer; int offset; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index ba43fb1768..ea0f7708dd 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -171,7 +171,14 @@ GLuint GLRenderManager::BindFramebufferAsTexture(GLRFramebuffer *fb, int binding } void GLRenderManager::CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLOffset2D dstPos, int aspectMask) { - + GLRStep * step = new GLRStep{ GLRStepType::COPY }; + step->copy.srcRect = srcRect; + step->copy.dstPos = dstPos; + step->copy.src = src; + step->copy.dst = dst; + step->copy.dstPos = dstPos; + step->copy.aspectMask = aspectMask; + steps_.push_back(step); } void GLRenderManager::BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLRect2D dstRect, int aspectMask, bool filter) { diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index a48103b539..ebec0abddc 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -141,6 +141,8 @@ public: void Take(GLDeleter &other) { shaders = std::move(other.shaders); programs = std::move(other.programs); + buffers = std::move(other.buffers); + textures = std::move(other.textures); } std::vector shaders; @@ -149,6 +151,19 @@ public: std::vector textures; }; +class GLRInputLayout { +public: + struct Entry { + int location; + int count; + GLenum type; + GLboolean normalized; + int stride; + intptr_t offset; + }; + std::vector entries; + int semanticsMask_ = 0; +}; class GLRenderManager { public: @@ -206,6 +221,18 @@ public: return step.create_program.program; } + GLRInputLayout *CreateInputLayout(std::vector &entries) { + GLRInitStep step{ GLRInitStepType::CREATE_PROGRAM }; + assert(shaders.size() <= ARRAY_SIZE(step.create_program.shaders)); + step.create_input_layout.inputLayout = new GLRInputLayout(); + step.create_input_layout.inputLayout->entries = std::move(entries); + for (auto &iter : entries) { + step.create_input_layout.inputLayout->semanticsMask_ |= 1 << iter.location; + } + initSteps_.push_back(step); + return step.create_input_layout.inputLayout; + } + void DeleteShader(GLRShader *shader) { deleter_.shaders.push_back(shader); } @@ -218,6 +245,9 @@ public: void DeleteTexture(GLRTexture *texture) { deleter_.textures.push_back(texture); } + void DeleteInputLayout(GLRInputLayout *inputLayout) { + + } void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil); GLuint BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment); @@ -266,6 +296,21 @@ public: curRenderStep_->commands.push_back(data); } + void BindInputLayout(GLRInputLayout *inputLayout, const void *offset) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::BIND_INPUT_LAYOUT }; + data.inputLayout.inputLayout = inputLayout; + data.inputLayout.offset = (intptr_t)offset; + curRenderStep_->commands.push_back(data); + } + + void UnbindInputLayout(GLRInputLayout *inputLayout) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::UNBIND_INPUT_LAYOUT }; + data.inputLayout.inputLayout = inputLayout; + curRenderStep_->commands.push_back(data); + } + void GenerateMipmap() { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::GENMIPS }; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index b247ca0b96..a7bcd9a7d0 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -294,22 +294,19 @@ bool OpenGLShaderModule::Compile(GLRenderManager *render, ShaderLanguage languag class OpenGLInputLayout : public InputLayout { public: + OpenGLInputLayout(GLRenderManager *render) : render_(render) {} ~OpenGLInputLayout(); void Apply(const void *base = nullptr); void Unapply(); - void Compile(); + void Compile(const InputLayoutDesc &desc); bool RequiresBuffer() { - return id_ != 0; + return false; } - InputLayoutDesc desc; - - int semanticsMask_; // Fast way to check what semantics to enable/disable. - int stride_; - GLuint id_; - bool needsEnable_; - intptr_t lastBase_; + GLRInputLayout *inputLayout_; +private: + GLRenderManager *render_; }; class OpenGLPipeline : public Pipeline { @@ -329,8 +326,6 @@ public: bool LinkShaders(); - int GetUniformLoc(const char *name); - bool RequiresBuffer() override { return inputLayout->RequiresBuffer(); } @@ -382,6 +377,9 @@ public: Buffer *CreateBuffer(size_t size, uint32_t usageFlags) override; Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) override; + void BeginFrame() override; + void EndFrame() override; + void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override; void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) override; @@ -411,7 +409,7 @@ public: // We render "upside down" to the backbuffer since GL is silly. y = targetHeight_ - (top + height); } - glstate.scissorRect.set(left, y, width, height); + renderManager_.SetScissor({ left, y, width, height }); } void SetViewports(int count, Viewport *viewports) override { @@ -542,10 +540,17 @@ OpenGLContext::~OpenGLContext() { boundSamplers_.clear(); } +void OpenGLContext::BeginFrame() { + renderManager_.BeginFrame(); +} + +void OpenGLContext::EndFrame() { + renderManager_.Finish(); +} + InputLayout *OpenGLContext::CreateInputLayout(const InputLayoutDesc &desc) { - OpenGLInputLayout *fmt = new OpenGLInputLayout(); - fmt->desc = desc; - fmt->Compile(); + OpenGLInputLayout *fmt = new OpenGLInputLayout(&renderManager_); + fmt->Compile(desc); return fmt; } @@ -869,28 +874,6 @@ Texture *OpenGLContext::CreateTexture(const TextureDesc &desc) { return new OpenGLTexture(&renderManager_, desc); } -OpenGLInputLayout::~OpenGLInputLayout() { - if (id_) { - glDeleteVertexArrays(1, &id_); - } -} - -void OpenGLInputLayout::Compile() { - int semMask = 0; - for (int i = 0; i < (int)desc.attributes.size(); i++) { - semMask |= 1 << desc.attributes[i].location; - } - semanticsMask_ = semMask; - - if (gl_extensions.ARB_vertex_array_object && gl_extensions.IsCoreContext) { - glGenVertexArrays(1, &id_); - } else { - id_ = 0; - } - needsEnable_ = true; - lastBase_ = -1; -} - DepthStencilState *OpenGLContext::CreateDepthStencilState(const DepthStencilStateDesc &desc) { OpenGLDepthStencilState *ds = new OpenGLDepthStencilState(); ds->depthTestEnabled = desc.depthTestEnabled; @@ -1138,10 +1121,9 @@ void OpenGLContext::Draw(int vertexCount, int offset) { curPipeline_->inputLayout->Apply(); ApplySamplers(); - glDrawArrays(curPipeline_->prim, offset, vertexCount); + renderManager_.Draw(curPipeline_->prim, offset, vertexCount); curPipeline_->inputLayout->Unapply(); - glBindBuffer(GL_ARRAY_BUFFER, 0); } void OpenGLContext::DrawIndexed(int vertexCount, int offset) { @@ -1154,16 +1136,12 @@ void OpenGLContext::DrawIndexed(int vertexCount, int offset) { glDrawElements(curPipeline_->prim, vertexCount, GL_UNSIGNED_INT, (const void *)(size_t)offset); curPipeline_->inputLayout->Unapply(); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { curPipeline_->inputLayout->Apply(vdata); ApplySamplers(); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDrawArrays(curPipeline_->prim, 0, vertexCount); curPipeline_->inputLayout->Unapply(); @@ -1174,83 +1152,70 @@ void OpenGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stenc Uint8x4ToFloat4(col, colorval); GLuint glMask = 0; if (mask & FBChannel::FB_COLOR_BIT) { - glClearColor(col[0], col[1], col[2], col[3]); glMask |= GL_COLOR_BUFFER_BIT; } if (mask & FBChannel::FB_DEPTH_BIT) { -#if defined(USING_GLES2) - glClearDepthf(depthVal); -#else - glClearDepth(depthVal); -#endif glMask |= GL_DEPTH_BUFFER_BIT; } if (mask & FBChannel::FB_STENCIL_BIT) { - glClearStencil(stencilVal); glMask |= GL_STENCIL_BUFFER_BIT; } - glClear(glMask); + renderManager_.Clear(colorval, depthVal, stencilVal, glMask); } DrawContext *T3DCreateGLContext() { return new OpenGLContext(); } +OpenGLInputLayout::~OpenGLInputLayout() { +} + +void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) { + int semMask = 0; + std::vector entries; + for (auto &attr : desc.attributes) { + GLRInputLayout::Entry entry; + entry.location = attr.location; + entry.stride = (GLsizei)desc.bindings[attr.binding].stride; + entry.offset = attr.offset; + switch (attr.format) { + case DataFormat::R32G32_FLOAT: + entry.count = 2; + entry.type = GL_FLOAT; + entry.normalized = GL_FALSE; + break; + case DataFormat::R32G32B32_FLOAT: + entry.count = 3; + entry.type = GL_FLOAT; + entry.normalized = GL_FALSE; + break; + case DataFormat::R32G32B32A32_FLOAT: + entry.count = 4; + entry.type = GL_FLOAT; + entry.normalized = GL_FALSE; + break; + case DataFormat::R8G8B8A8_UNORM: + entry.count = 4; + entry.type = GL_UNSIGNED_BYTE; + entry.normalized = GL_TRUE; + break; + case DataFormat::UNDEFINED: + default: + ELOG("Thin3DGLVertexFormat: Invalid or unknown component type applied."); + break; + } + + entries.push_back(entry); + } + inputLayout_ = render_->CreateInputLayout(entries); +} + void OpenGLInputLayout::Apply(const void *base) { - if (id_ != 0) { - glBindVertexArray(id_); - } - - if (needsEnable_ || id_ == 0) { - for (int i = 0; i < SEM_MAX; i++) { - if (semanticsMask_ & (1 << i)) { - glEnableVertexAttribArray(i); - } - } - if (id_ != 0) { - needsEnable_ = false; - } - } - - intptr_t b = (intptr_t)base; - if (b != lastBase_) { - for (size_t i = 0; i < desc.attributes.size(); i++) { - GLsizei stride = (GLsizei)desc.bindings[desc.attributes[i].binding].stride; - switch (desc.attributes[i].format) { - case DataFormat::R32G32_FLOAT: - glVertexAttribPointer(desc.attributes[i].location, 2, GL_FLOAT, GL_FALSE, stride, (void *)(b + (intptr_t)desc.attributes[i].offset)); - break; - case DataFormat::R32G32B32_FLOAT: - glVertexAttribPointer(desc.attributes[i].location, 3, GL_FLOAT, GL_FALSE, stride, (void *)(b + (intptr_t)desc.attributes[i].offset)); - break; - case DataFormat::R32G32B32A32_FLOAT: - glVertexAttribPointer(desc.attributes[i].location, 4, GL_FLOAT, GL_FALSE, stride, (void *)(b + (intptr_t)desc.attributes[i].offset)); - break; - case DataFormat::R8G8B8A8_UNORM: - glVertexAttribPointer(desc.attributes[i].location, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, (void *)(b + (intptr_t)desc.attributes[i].offset)); - break; - case DataFormat::UNDEFINED: - default: - ELOG("Thin3DGLVertexFormat: Invalid or unknown component type applied."); - break; - } - } - if (id_ != 0) { - lastBase_ = b; - } - } + render_->BindInputLayout(inputLayout_, base); } void OpenGLInputLayout::Unapply() { - if (id_ == 0) { - for (int i = 0; i < (int)SEM_MAX; i++) { - if (semanticsMask_ & (1 << i)) { - glDisableVertexAttribArray(i); - } - } - } else { - glBindVertexArray(0); - } + render_->UnbindInputLayout(inputLayout_); } // On PC, we always use GL_DEPTH24_STENCIL8. @@ -1579,12 +1544,12 @@ void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int s int aspect = 0; if (channelBits & FB_COLOR_BIT) { - aspect |= GLR_ASPECT_COLOR; + aspect |= GL_COLOR_BUFFER_BIT; } else if (channelBits & (FB_STENCIL_BIT | FB_DEPTH_BIT)) { if (channelBits & FB_STENCIL_BIT) - aspect |= GLR_ASPECT_STENCIL; + aspect |= GL_STENCIL_BUFFER_BIT; if (channelBits & FB_DEPTH_BIT) - aspect |= GLR_ASPECT_DEPTH; + aspect |= GL_DEPTH_BUFFER_BIT; } renderManager_.CopyFramebuffer(src->framebuffer, GLRect2D{ srcX, srcY, width, height }, dst->framebuffer, GLOffset2D{ dstX, dstY }, aspect); } From e1bb4441d847bb9600402d86e8f201ec3ee66841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Nov 2017 21:51:17 +0100 Subject: [PATCH 005/291] First garbage graphics output! --- ext/native/thin3d/GLQueueRunner.cpp | 34 +++++++++++++++++++++++---- ext/native/thin3d/GLRenderManager.cpp | 4 ++++ ext/native/thin3d/GLRenderManager.h | 11 +++++---- ext/native/thin3d/thin3d_gl.cpp | 22 ++++++++++------- 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index f5275fdc72..0468cdb014 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -19,7 +19,12 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { const GLRInitStep &step = steps[i]; switch (step.stepType) { case GLRInitStepType::CREATE_TEXTURE: + { + GLRTexture *tex = step.create_texture.texture; + glGenTextures(1, &tex->texture); + glBindTexture(tex->target, tex->texture); break; + } case GLRInitStepType::CREATE_BUFFER: { GLRBuffer *buffer = step.create_buffer.buffer; @@ -122,8 +127,14 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { glTexImage2D(tex->target, step.texture_image.level, step.texture_image.internalFormat, step.texture_image.width, step.texture_image.height, 0, step.texture_image.format, step.texture_image.type, step.texture_image.data); delete[] step.texture_image.data; CHECK_GL_ERROR_IF_DEBUG(); + 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_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); break; } + default: + Crash(); } } } @@ -147,6 +158,9 @@ void GLQueueRunner::RunSteps(const std::vector &steps) { case GLRStepType::READBACK_IMAGE: PerformReadbackImage(step); break; + default: + Crash(); + break; } delete steps[i]; } @@ -172,9 +186,6 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { // This is supposed to bind a vulkan render pass to the command buffer. PerformBindFramebufferAsRenderTarget(step); - int curWidth = step.render.framebuffer ? step.render.framebuffer->width : 0; // vulkan_->GetBackbufferWidth(); - int curHeight = step.render.framebuffer ? step.render.framebuffer->height : 0; // vulkan_->GetBackbufferHeight(); - GLRFramebuffer *fb = step.render.framebuffer; GLRProgram *curProgram = nullptr; GLint activeTexture = GL_TEXTURE0; @@ -293,7 +304,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glEnableVertexAttribArray(i); } } - for (auto &entry: layout->entries) { + for (int i = 0; i < layout->entries.size(); i++) { + auto &entry = layout->entries[i]; glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.inputLayout.offset + entry.offset)); } break; @@ -325,12 +337,26 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter); break; + case GLRRenderCommand::RASTER: + if (c.raster.cullEnable) { + glEnable(GL_CULL_FACE); + glFrontFace(c.raster.frontFace); + glCullFace(c.raster.cullFace); + } else { + glDisable(GL_CULL_FACE); + } + break; + default: + Crash(); + break; } } + if (activeTexture != GL_TEXTURE0) glActiveTexture(GL_TEXTURE0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glDisable(GL_SCISSOR_TEST); } void GLQueueRunner::PerformCopy(const GLRStep &step) { diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index ea0f7708dd..ddbaca0a19 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -224,12 +224,14 @@ void GLRenderManager::Finish() { FrameData &frameData = frameData_[curFrame]; if (!useThread_) { frameData.steps = std::move(steps_); + frameData.initSteps = std::move(initSteps_); frameData.type = GLRRunType::END; Run(curFrame); } else { std::unique_lock lock(frameData.pull_mutex); VLOG("PUSH: Frame[%d].readyForRun = true", curFrame); frameData.steps = std::move(steps_); + frameData.initSteps = std::move(initSteps_); frameData.readyForRun = true; frameData.type = GLRRunType::END; frameData.pull_condVar.notify_all(); @@ -239,6 +241,8 @@ void GLRenderManager::Finish() { frameData_[curFrame_].deleter.Take(deleter_); curFrame_++; + if (curFrame_ >= MAX_INFLIGHT_FRAMES) + curFrame_ = 0; insideFrame_ = false; } diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index ebec0abddc..fe18490bd8 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -217,16 +217,16 @@ public: for (int i = 0; i < shaders.size(); i++) { step.create_program.shaders[i] = shaders[i]; } + step.create_program.num_shaders = (int)shaders.size(); initSteps_.push_back(step); return step.create_program.program; } GLRInputLayout *CreateInputLayout(std::vector &entries) { - GLRInitStep step{ GLRInitStepType::CREATE_PROGRAM }; - assert(shaders.size() <= ARRAY_SIZE(step.create_program.shaders)); + GLRInitStep step{ GLRInitStepType::CREATE_INPUT_LAYOUT }; step.create_input_layout.inputLayout = new GLRInputLayout(); - step.create_input_layout.inputLayout->entries = std::move(entries); - for (auto &iter : entries) { + step.create_input_layout.inputLayout->entries = entries; + for (auto &iter : step.create_input_layout.inputLayout->entries) { step.create_input_layout.inputLayout->semanticsMask_ |= 1 << iter.location; } initSteps_.push_back(step); @@ -271,6 +271,7 @@ public: void TextureImage(GLRTexture *texture, int level, int width, int height, GLenum internalFormat, GLenum format, GLenum type, uint8_t *data) { GLRInitStep step{ GLRInitStepType::TEXTURE_IMAGE }; + step.texture_image.texture = texture; step.texture_image.data = data; step.texture_image.internalFormat = internalFormat; step.texture_image.format = format; @@ -368,7 +369,7 @@ public: void SetUniformM4x4(const char *name, const float *udata) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; + GLRRenderData data{ GLRRenderCommand::UNIFORMMATRIX }; data.uniformMatrix4.name = name; memcpy(data.uniformMatrix4.m, udata, sizeof(float) * 16); curRenderStep_->commands.push_back(data); diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index a7bcd9a7d0..8aaff8a5c7 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -618,8 +618,6 @@ OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : GLenum target = TypeToTarget(desc.type); tex_ = render->CreateTexture(target, width_, height_); - render->BindTexture(0, tex_); - canWrap_ = isPowerOf2(width_) && isPowerOf2(height_); mipLevels_ = desc.mipLevels; if (!desc.initData.size()) @@ -634,7 +632,6 @@ OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : } mipLevels_ = desc.generateMips ? desc.mipLevels : level; - render->SetTextureSampler(GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_LINEAR, mipLevels_ > 1 ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); /* #ifdef USING_GLES2 if (gl_extensions.GLES3) { @@ -650,8 +647,6 @@ OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : AutoGenMipmaps(); } - // Unbind. - render->BindTexture(0, nullptr); } OpenGLTexture::~OpenGLTexture() { @@ -664,7 +659,7 @@ OpenGLTexture::~OpenGLTexture() { void OpenGLTexture::AutoGenMipmaps() { if (!generatedMips_) { - render_->BindTexture(0, tex_); + // Assumes the texture is bound for editing render_->GenerateMipmap(); generatedMips_ = true; } @@ -1133,8 +1128,8 @@ void OpenGLContext::DrawIndexed(int vertexCount, int offset) { // Note: ibuf binding is stored in the VAO, so call this after binding the fmt. curIBuffer_->Bind(curIBufferOffset_); - glDrawElements(curPipeline_->prim, vertexCount, GL_UNSIGNED_INT, (const void *)(size_t)offset); - + renderManager_.DrawIndexed(curPipeline_->prim, vertexCount, GL_UNSIGNED_INT, (void *)(intptr_t)offset); + curPipeline_->inputLayout->Unapply(); } @@ -1142,7 +1137,7 @@ void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { curPipeline_->inputLayout->Apply(vdata); ApplySamplers(); - glDrawArrays(curPipeline_->prim, 0, vertexCount); + renderManager_.Draw(curPipeline_->prim, 0, vertexCount); curPipeline_->inputLayout->Unapply(); } @@ -1483,6 +1478,14 @@ void OpenGLContext::fbo_unbind() { } void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp) { + OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; + GLRRenderPassAction color = (GLRRenderPassAction)rp.color; + GLRRenderPassAction depth = (GLRRenderPassAction)rp.depth; + + renderManager_.BindFramebufferAsRenderTarget(fb ? fb->framebuffer : nullptr, color, depth, rp.clearColor, rp.clearDepth, rp.clearStencil); + +#if 0 + CHECK_GL_ERROR_IF_DEBUG(); curFB_ = (OpenGLFramebuffer *)fbo; if (fbo) { @@ -1536,6 +1539,7 @@ void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const Render glstate.stencilMask.restore(); } CHECK_GL_ERROR_IF_DEBUG(); +#endif } void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) { From a3bcd91a31421b87b1e0b787e332511a808f201b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Nov 2017 22:15:12 +0100 Subject: [PATCH 006/291] Fix clears and textures. Things still broken due to memory overwrites. --- ext/native/thin3d/GLQueueRunner.cpp | 9 +++--- ext/native/thin3d/GLQueueRunner.h | 12 ++++---- ext/native/thin3d/GLRenderManager.cpp | 43 ++++++++++++++++----------- ext/native/thin3d/GLRenderManager.h | 4 +-- ext/native/thin3d/thin3d_gl.cpp | 27 ++++++++--------- 5 files changed, 49 insertions(+), 46 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 0468cdb014..9cf5ee446c 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -176,16 +176,15 @@ void GLQueueRunner::PerformBlit(const GLRStep &step) { void GLQueueRunner::PerformRenderPass(const GLRStep &step) { // Don't execute empty renderpasses. - if (step.commands.empty() && step.render.color == GLRRenderPassAction::KEEP && step.render.depthStencil == GLRRenderPassAction::KEEP) { + if (step.commands.empty()) { // Nothing to do. return; } - glEnable(GL_SCISSOR_TEST); - - // This is supposed to bind a vulkan render pass to the command buffer. PerformBindFramebufferAsRenderTarget(step); + glEnable(GL_SCISSOR_TEST); + GLRFramebuffer *fb = step.render.framebuffer; GLRProgram *curProgram = nullptr; GLint activeTexture = GL_TEXTURE0; @@ -224,7 +223,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glClearDepth(c.clear.clearZ); #endif } - if (c.clear.clearMask & GL_STENCIL) { + if (c.clear.clearMask & GL_STENCIL_BUFFER_BIT) { glClearStencil(c.clear.clearStencil); } glClear(c.clear.clearMask); diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index ff8be97b6b..d684533cf2 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -22,6 +22,7 @@ struct GLOffset2D { class GLRShader; class GLRTexture; class GLRBuffer; +class GLRFramebuffer; class GLRProgram; class GLRInputLayout; @@ -39,6 +40,7 @@ enum class GLRRenderCommand : uint8_t { CLEAR, BINDPROGRAM, BINDTEXTURE, + BIND_FB_TEXTURE, BIND_INPUT_LAYOUT, UNBIND_INPUT_LAYOUT, GENMIPS, @@ -112,6 +114,11 @@ struct GLRRenderData { int slot; GLRTexture *texture; } texture; + struct { + int slot; + GLRFramebuffer *framebuffer; + int aspect; + } bind_fb_texture; struct { GLRProgram *program; } program; @@ -231,11 +238,6 @@ struct GLRStep { union { struct { GLRFramebuffer *framebuffer; - GLRRenderPassAction color; - GLRRenderPassAction depthStencil; - uint32_t clearColor; - float clearDepth; - int clearStencil; int numDraws; } render; struct { diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index ddbaca0a19..7e87089660 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -138,13 +138,6 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende return; } } - if (curRenderStep_ && curRenderStep_->commands.size() == 0 && curRenderStep_->render.color == GLRRenderPassAction::KEEP && curRenderStep_->render.depthStencil == GLRRenderPassAction::KEEP) { - // Can trivially kill the last empty render step. - assert(steps_.back() == curRenderStep_); - delete steps_.back(); - steps_.pop_back(); - curRenderStep_ = nullptr; - } if (curRenderStep_ && curRenderStep_->commands.size() == 0) { VLOG("Empty render step. Usually happens after uploading pixels.."); } @@ -152,22 +145,36 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende GLRStep *step = new GLRStep{ GLRStepType::RENDER }; // This is what queues up new passes, and can end previous ones. step->render.framebuffer = fb; - step->render.color = color; - step->render.depthStencil = depth; - step->render.clearColor = clearColor; - step->render.clearDepth = clearDepth; - step->render.clearStencil = clearStencil; step->render.numDraws = 0; steps_.push_back(step); + GLuint clearMask = 0; + GLRRenderData data; + data.cmd = GLRRenderCommand::CLEAR; + if (color == GLRRenderPassAction::CLEAR) { + clearMask |= GL_COLOR_BUFFER_BIT; + data.clear.clearColor = clearColor; + } + if (depth == GLRRenderPassAction::CLEAR) { + clearMask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; + data.clear.clearZ = clearDepth; + data.clear.clearStencil = clearStencil; + } + if (clearMask) { + data.clear.clearMask = clearMask; + step->commands.push_back(data); + } + curRenderStep_ = step; - curWidth_ = fb ? fb->width : 0; // vulkan_->GetBackbufferWidth(); - curHeight_ = fb ? fb->height : 0; // vulkan_->GetBackbufferHeight(); } -GLuint GLRenderManager::BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment) { - // Easy in GL. - return fb->color.texture; +void GLRenderManager::BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::BIND_FB_TEXTURE }; + data.bind_fb_texture.slot = binding; + data.bind_fb_texture.framebuffer = fb; + data.bind_fb_texture.aspect = aspectBit; + curRenderStep_->commands.push_back(data); } void GLRenderManager::CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLOffset2D dstPos, int aspectMask) { @@ -182,7 +189,7 @@ void GLRenderManager::CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLR } void GLRenderManager::BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLRect2D dstRect, int aspectMask, bool filter) { - + Crash(); } void GLRenderManager::BeginFrame() { diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index fe18490bd8..dc9e724425 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -250,7 +250,7 @@ public: } void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil); - GLuint BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment); + void BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment); bool CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride); void CopyImageToMemorySync(GLuint texture, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride); @@ -492,8 +492,6 @@ private: FrameData frameData_[MAX_INFLIGHT_FRAMES]; // Submission time state - int curWidth_; - int curHeight_; bool insideFrame_ = false; GLRStep *curRenderStep_ = nullptr; std::vector steps_; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 8aaff8a5c7..f7309202b2 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -475,7 +475,12 @@ public: } uintptr_t GetNativeObject(NativeObject obj) override { - return 0; + switch (obj) { + case NativeObject::RENDER_MANAGER: + return (uintptr_t)&renderManager_; + default: + return 0; + } } void HandleEvent(Event ev, int width, int height, void *param1, void *param2) override {} @@ -783,6 +788,9 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int return; } + if (stride == 0) + stride = width; + // Make a copy of data with stride eliminated. uint8_t *texData = new uint8_t[width * height * alignment]; for (int y = 0; y < height; y++) { @@ -791,7 +799,6 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int render_->TextureImage(tex_, level, width, height, internalFormat, format, type, texData); } - #ifdef DEBUG_READ_PIXELS // TODO: Make more generic. static void LogReadPixelsError(GLenum error) { @@ -1589,19 +1596,9 @@ bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, in void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int color) { OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; - if (!fb) - return; - if (binding != 0) - glActiveTexture(GL_TEXTURE0 + binding); - switch (channelBit) { - case FB_DEPTH_BIT: - glBindTexture(GL_TEXTURE_2D, fb->z_buffer ? fb->z_buffer : fb->z_stencil_buffer); - case FB_COLOR_BIT: - default: - glBindTexture(GL_TEXTURE_2D, fb->color_texture); - break; - } - glActiveTexture(GL_TEXTURE0); + + GLuint aspect = 0; + renderManager_.BindFramebufferAsTexture(fb->framebuffer, binding, (int)channelBit, color); } OpenGLFramebuffer::~OpenGLFramebuffer() { From 60a966c5ec3e18625564b60ab11c076a271c7a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 19 Nov 2017 00:23:52 +0100 Subject: [PATCH 007/291] PushBuffer added. Thin3d works now on top of GLRenderManager, except framebuffers. --- Common/Vulkan/VulkanMemory.cpp | 2 +- ext/native/thin3d/GLQueueRunner.cpp | 14 ++- ext/native/thin3d/GLQueueRunner.h | 5 + ext/native/thin3d/GLRenderManager.cpp | 84 +++++++++++++- ext/native/thin3d/GLRenderManager.h | 155 ++++++++++++++++++++++++-- ext/native/thin3d/thin3d_gl.cpp | 75 ++++++++----- 6 files changed, 298 insertions(+), 37 deletions(-) diff --git a/Common/Vulkan/VulkanMemory.cpp b/Common/Vulkan/VulkanMemory.cpp index d19467847e..721b97e5b5 100644 --- a/Common/Vulkan/VulkanMemory.cpp +++ b/Common/Vulkan/VulkanMemory.cpp @@ -76,7 +76,7 @@ bool VulkanPushBuffer::AddBuffer() { } buf_ = buffers_.size(); - buffers_.resize(buf_ + 1); + buffers_.resize(buf_ + 1); // Why not push_back? buffers_[buf_] = info; return true; } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 9cf5ee446c..03c6404fa9 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -36,8 +36,10 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { case GLRInitStepType::BUFFER_SUBDATA: { GLRBuffer *buffer = step.buffer_subdata.buffer; - glBufferSubData(buffer->buffer, step.buffer_subdata.offset, step.buffer_subdata.size, step.buffer_subdata.data); - delete[] step.buffer_subdata.data; + glBindBuffer(GL_ARRAY_BUFFER, buffer->buffer); + glBufferSubData(GL_ARRAY_BUFFER, step.buffer_subdata.offset, step.buffer_subdata.size, step.buffer_subdata.data); + if (step.buffer_subdata.deleteData) + delete[] step.buffer_subdata.data; break; } case GLRInitStepType::CREATE_PROGRAM: @@ -184,6 +186,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { PerformBindFramebufferAsRenderTarget(step); glEnable(GL_SCISSOR_TEST); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); GLRFramebuffer *fb = step.render.framebuffer; GLRProgram *curProgram = nullptr; @@ -309,6 +313,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } break; } + case GLRRenderCommand::BIND_VERTEX_BUFFER: + { + GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0; + glBindBuffer(GL_ARRAY_BUFFER, buf); + break; + } case GLRRenderCommand::UNBIND_INPUT_LAYOUT: { GLRInputLayout *layout = c.inputLayout.inputLayout; diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index d684533cf2..ccd07a3c17 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -42,6 +42,7 @@ enum class GLRRenderCommand : uint8_t { BINDTEXTURE, BIND_FB_TEXTURE, BIND_INPUT_LAYOUT, + BIND_VERTEX_BUFFER, UNBIND_INPUT_LAYOUT, GENMIPS, DRAW, @@ -119,6 +120,9 @@ struct GLRRenderData { GLRFramebuffer *framebuffer; int aspect; } bind_fb_texture; + struct { + GLRBuffer *buffer; + } bind_buffer; struct { GLRProgram *program; } program; @@ -195,6 +199,7 @@ struct GLRInitStep { int offset; int size; uint8_t *data; // owned, delete[]-d + bool deleteData; } buffer_subdata; struct { GLRTexture *texture; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 7e87089660..226aed1458 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -341,4 +341,86 @@ void GLRenderManager::Wipe() { delete step; } steps_.clear(); -} \ No newline at end of file +} + +GLPushBuffer::GLPushBuffer(GLRenderManager *render, size_t size) : render_(render), buf_(0), offset_(0), size_(size), writePtr_(nullptr) { + bool res = AddBuffer(); + assert(res); +} + +GLPushBuffer::~GLPushBuffer() { + assert(buffers_.empty()); +} + +void GLPushBuffer::Unmap() { + assert(writePtr_); + // Here we should simply upload everything to the buffers. + // Might be worth trying with size_ instead of offset_, so the driver can replace the whole buffer. + // At least if it's close. + render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].deviceMemory, false); + writePtr_ = nullptr; +} + +bool GLPushBuffer::AddBuffer() { + BufInfo info; + info.deviceMemory = new uint8_t[size_]; + info.buffer = render_->CreateBuffer(GL_ARRAY_BUFFER, size_, GL_DYNAMIC_DRAW); + buf_ = buffers_.size(); + buffers_.resize(buf_ + 1); + buffers_[buf_] = info; + return true; +} + +void GLPushBuffer::Destroy() { + for (BufInfo &info : buffers_) { + render_->DeleteBuffer(info.buffer); + delete[] info.deviceMemory; + } + buffers_.clear(); +} + +void GLPushBuffer::NextBuffer(size_t minSize) { + // First, unmap the current memory. + Unmap(); + + buf_++; + if (buf_ >= buffers_.size() || minSize > size_) { + // Before creating the buffer, adjust to the new size_ if necessary. + while (size_ < minSize) { + size_ <<= 1; + } + + bool res = AddBuffer(); + assert(res); + if (!res) { + // Let's try not to crash at least? + buf_ = 0; + } + } + + // Now, move to the next buffer and map it. + offset_ = 0; + Map(); +} + +void GLPushBuffer::Defragment() { + if (buffers_.size() <= 1) { + return; + } + + // Okay, we have more than one. Destroy them all and start over with a larger one. + size_t newSize = size_ * buffers_.size(); + Destroy(); + + size_ = newSize; + bool res = AddBuffer(); + assert(res); +} + +size_t GLPushBuffer::GetTotalSize() const { + size_t sum = 0; + if (buffers_.size() > 1) + sum += size_ * (buffers_.size() - 1); + sum += offset_; + return sum; +} diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index dc9e724425..b1559fb697 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -18,6 +18,8 @@ struct GLRImage { void GLCreateImage(GLRImage &img, int width, int height, GLint format, bool color); +class GLRInputLayout; + class GLRFramebuffer { public: GLRFramebuffer(int _width, int _height) { @@ -143,12 +145,14 @@ public: programs = std::move(other.programs); buffers = std::move(other.buffers); textures = std::move(other.textures); + inputLayouts = std::move(other.inputLayouts); } std::vector shaders; std::vector programs; std::vector buffers; std::vector textures; + std::vector inputLayouts; }; class GLRInputLayout { @@ -195,6 +199,8 @@ public: GLRBuffer *CreateBuffer(GLuint target, int size, GLuint usage) { GLRInitStep step{ GLRInitStepType::CREATE_BUFFER }; step.create_buffer.buffer = new GLRBuffer(target); + step.create_buffer.size = size; + step.create_buffer.usage = usage; initSteps_.push_back(step); return step.create_buffer.buffer; } @@ -246,7 +252,7 @@ public: deleter_.textures.push_back(texture); } void DeleteInputLayout(GLRInputLayout *inputLayout) { - + deleter_.inputLayouts.push_back(inputLayout); } void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil); @@ -257,8 +263,8 @@ public: void CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLOffset2D dstPos, int aspectMask); void BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLRect2D dstRect, int aspectMask, bool filter); - // Takes ownership of data. - void BufferSubdata(GLRBuffer *buffer, int offset, int size, uint8_t *data) { + // Takes ownership of data if deleteData = true. + void BufferSubdata(GLRBuffer *buffer, int offset, int size, uint8_t *data, bool deleteData = true) { // TODO: Maybe should be a render command instead of an init command? When possible it's better as // an init command, that's for sure. GLRInitStep step{ GLRInitStepType::BUFFER_SUBDATA }; @@ -266,6 +272,7 @@ public: step.buffer_subdata.offset = offset; step.buffer_subdata.size = size; step.buffer_subdata.data = data; + step.buffer_subdata.deleteData = deleteData; initSteps_.push_back(step); } @@ -297,8 +304,16 @@ public: curRenderStep_->commands.push_back(data); } + void BindVertexBuffer(GLRBuffer *buffer) { // Want to support an offset but can't in ES 2.0. We supply an offset when binding the buffers instead. + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::BIND_VERTEX_BUFFER }; + data.bind_buffer.buffer = buffer; + curRenderStep_->commands.push_back(data); + } + void BindInputLayout(GLRInputLayout *inputLayout, const void *offset) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + assert(inputLayout); GLRRenderData data{ GLRRenderCommand::BIND_INPUT_LAYOUT }; data.inputLayout.inputLayout = inputLayout; data.inputLayout.offset = (intptr_t)offset; @@ -307,6 +322,7 @@ public: void UnbindInputLayout(GLRInputLayout *inputLayout) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + assert(inputLayout); GLRRenderData data{ GLRRenderCommand::UNBIND_INPUT_LAYOUT }; data.inputLayout.inputLayout = inputLayout; curRenderStep_->commands.push_back(data); @@ -375,6 +391,20 @@ public: curRenderStep_->commands.push_back(data); } + void SetBlendAndMask(int colorMask, bool blendEnabled, GLenum srcColor, GLenum dstColor, GLenum srcAlpha, GLenum dstAlpha, GLenum funcColor, GLenum funcAlpha) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::BLEND }; + data.blend.mask = colorMask; + data.blend.enabled = blendEnabled; + data.blend.srcColor = srcColor; + data.blend.dstColor = dstColor; + data.blend.srcAlpha = srcAlpha; + data.blend.dstAlpha = dstAlpha; + data.blend.funcColor = funcColor; + data.blend.funcAlpha = funcAlpha; + curRenderStep_->commands.push_back(data); + } + void SetStencil(bool enabled, GLenum func, GLenum sFail, GLenum zFail, GLenum pass, uint8_t writeMask, uint8_t compareMask, uint8_t refValue) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::STENCIL }; @@ -450,6 +480,10 @@ public: enum { MAX_INFLIGHT_FRAMES = 3 }; + int GetCurFrame() const { + return curFrame_; + } + private: void BeginSubmitFrame(int frame); void EndSubmitFrame(int frame); @@ -461,10 +495,6 @@ private: void StopThread(); - int GetCurFrame() const { - return curFrame_; - } - // Per-frame data, round-robin so we can overlap submission with execution of the previous frame. struct FrameData { std::mutex push_mutex; @@ -511,3 +541,114 @@ private: int curFrame_ = 0; }; + +// Similar to VulkanPushBuffer but uses really stupid tactics - collect all the data in RAM then do a big +// memcpy/buffer upload at the end. This can however be optimized with glBufferStorage on chips that support that +// for massive boosts. +class GLPushBuffer { +public: + struct BufInfo { + GLRBuffer *buffer; + uint8_t *deviceMemory; + }; + +public: + GLPushBuffer(GLRenderManager *render, size_t size); + ~GLPushBuffer(); + + void Destroy(); + + void Reset() { offset_ = 0; } + + // Needs context in case of defragment. + void Begin() { + buf_ = 0; + offset_ = 0; + // Note: we must defrag because some buffers may be smaller than size_. + Defragment(); + Map(); + assert(writePtr_); + } + + void BeginNoReset() { + Map(); + } + + void End() { + Unmap(); + } + + void Map() { + assert(!writePtr_); + // VkResult res = vkMapMemory(device_, buffers_[buf_].deviceMemory, 0, size_, 0, (void **)(&writePtr_)); + writePtr_ = buffers_[buf_].deviceMemory; + assert(writePtr_); + } + + void Unmap(); + + // When using the returned memory, make sure to bind the returned vkbuf. + // This will later allow for handling overflow correctly. + size_t Allocate(size_t numBytes, GLRBuffer **vkbuf) { + size_t out = offset_; + offset_ += (numBytes + 3) & ~3; // Round up to 4 bytes. + + if (offset_ >= size_) { + NextBuffer(numBytes); + out = offset_; + offset_ += (numBytes + 3) & ~3; + } + *vkbuf = buffers_[buf_].buffer; + return out; + } + + // Returns the offset that should be used when binding this buffer to get this data. + size_t Push(const void *data, size_t size, GLRBuffer **vkbuf) { + assert(writePtr_); + size_t off = Allocate(size, vkbuf); + memcpy(writePtr_ + off, data, size); + return off; + } + + uint32_t PushAligned(const void *data, size_t size, int align, GLRBuffer **vkbuf) { + assert(writePtr_); + offset_ = (offset_ + align - 1) & ~(align - 1); + size_t off = Allocate(size, vkbuf); + memcpy(writePtr_ + off, data, size); + return (uint32_t)off; + } + + size_t GetOffset() const { + return offset_; + } + + // "Zero-copy" variant - you can write the data directly as you compute it. + // Recommended. + void *Push(size_t size, uint32_t *bindOffset, GLRBuffer **vkbuf) { + assert(writePtr_); + size_t off = Allocate(size, vkbuf); + *bindOffset = (uint32_t)off; + return writePtr_ + off; + } + void *PushAligned(size_t size, uint32_t *bindOffset, GLRBuffer **vkbuf, int align) { + assert(writePtr_); + offset_ = (offset_ + align - 1) & ~(align - 1); + size_t off = Allocate(size, vkbuf); + *bindOffset = (uint32_t)off; + return writePtr_ + off; + } + + size_t GetTotalSize() const; + +private: + bool AddBuffer(); + void NextBuffer(size_t minSize); + void Defragment(); + + GLRenderManager *render_; + std::vector buffers_; + size_t buf_; + size_t offset_; + size_t size_; + uint8_t *writePtr_; +}; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index f7309202b2..5d3004d3ba 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -176,14 +176,7 @@ public: // uint32_t fixedColor; void Apply(GLRenderManager *render) { - if (enabled) { - glEnable(GL_BLEND); - glBlendEquationSeparate(eqCol, eqAlpha); - glBlendFuncSeparate(srcCol, dstCol, srcAlpha, dstAlpha); - } else { - glDisable(GL_BLEND); - } - glColorMask(colorMask & 1, (colorMask >> 1) & 1, (colorMask >> 2) & 1, (colorMask >> 3) & 1); + render->SetBlendAndMask(colorMask, enabled, srcCol, dstCol, srcAlpha, dstAlpha, eqCol, eqAlpha); } }; @@ -297,14 +290,13 @@ public: OpenGLInputLayout(GLRenderManager *render) : render_(render) {} ~OpenGLInputLayout(); - void Apply(const void *base = nullptr); - void Unapply(); void Compile(const InputLayoutDesc &desc); bool RequiresBuffer() { return false; } GLRInputLayout *inputLayout_; + int stride; private: GLRenderManager *render_; }; @@ -510,6 +502,13 @@ private: // Framebuffer state GLuint currentDrawHandle_ = 0; GLuint currentReadHandle_ = 0; + + // Frames in flight is not such a strict concept as with Vulkan until we start using glBufferStorage and fences. + // But might as well have the structure ready, and can't hurt to rotate buffers. + struct FrameData { + GLPushBuffer *push; + }; + FrameData frameData_[GLRenderManager::MAX_INFLIGHT_FRAMES]; }; OpenGLContext::OpenGLContext() { @@ -538,18 +537,29 @@ OpenGLContext::OpenGLContext() { default: caps_.vendor = GPUVendor::VENDOR_UNKNOWN; break; + } + for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { + frameData_[i].push = new GLPushBuffer(&renderManager_, 64 * 1024); } } OpenGLContext::~OpenGLContext() { + for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { + frameData_[i].push->Destroy(); + delete frameData_[i].push; + } boundSamplers_.clear(); } void OpenGLContext::BeginFrame() { renderManager_.BeginFrame(); + FrameData &frameData = frameData_[renderManager_.GetCurFrame()]; + frameData.push->Begin(); } void OpenGLContext::EndFrame() { + FrameData &frameData = frameData_[renderManager_.GetCurFrame()]; + frameData.push->End(); // upload the data! renderManager_.Finish(); } @@ -1120,33 +1130,50 @@ void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) { void OpenGLContext::Draw(int vertexCount, int offset) { curVBuffers_[0]->Bind(curVBufferOffsets_[0]); - curPipeline_->inputLayout->Apply(); + renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, 0); ApplySamplers(); renderManager_.Draw(curPipeline_->prim, offset, vertexCount); - curPipeline_->inputLayout->Unapply(); + renderManager_.UnbindInputLayout(curPipeline_->inputLayout->inputLayout_); } void OpenGLContext::DrawIndexed(int vertexCount, int offset) { curVBuffers_[0]->Bind(curVBufferOffsets_[0]); - curPipeline_->inputLayout->Apply(); + renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, 0); ApplySamplers(); // Note: ibuf binding is stored in the VAO, so call this after binding the fmt. curIBuffer_->Bind(curIBufferOffset_); renderManager_.DrawIndexed(curPipeline_->prim, vertexCount, GL_UNSIGNED_INT, (void *)(intptr_t)offset); - - curPipeline_->inputLayout->Unapply(); + renderManager_.UnbindInputLayout(curPipeline_->inputLayout->inputLayout_); } void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { - curPipeline_->inputLayout->Apply(vdata); +#if 1 + int stride = curPipeline_->inputLayout->stride; + size_t dataSize = stride * vertexCount; + + FrameData &frameData = frameData_[renderManager_.GetCurFrame()]; + + GLRBuffer *buf; + size_t offset = frameData.push->Push(vdata, dataSize, &buf); + ApplySamplers(); - renderManager_.Draw(curPipeline_->prim, 0, vertexCount); + renderManager_.BindVertexBuffer(buf); + renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, (void *)offset); - curPipeline_->inputLayout->Unapply(); + renderManager_.Draw(curPipeline_->prim, 0, vertexCount); + renderManager_.UnbindInputLayout(curPipeline_->inputLayout->inputLayout_); + renderManager_.BindVertexBuffer(nullptr); +#else + ApplySamplers(); + renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, (void *)vdata); + renderManager_.Draw(curPipeline_->prim, 0, vertexCount); + renderManager_.UnbindInputLayout(curPipeline_->inputLayout->inputLayout_); + +#endif } void OpenGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) { @@ -1174,6 +1201,10 @@ OpenGLInputLayout::~OpenGLInputLayout() { void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) { int semMask = 0; + + // This is only accurate if there's only one stream. But whatever, for now. + stride = (GLsizei)desc.bindings[0].stride; + std::vector entries; for (auto &attr : desc.attributes) { GLRInputLayout::Entry entry; @@ -1212,14 +1243,6 @@ void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) { inputLayout_ = render_->CreateInputLayout(entries); } -void OpenGLInputLayout::Apply(const void *base) { - render_->BindInputLayout(inputLayout_, base); -} - -void OpenGLInputLayout::Unapply() { - render_->UnbindInputLayout(inputLayout_); -} - // On PC, we always use GL_DEPTH24_STENCIL8. // On Android, we try to use what's available. From 9340260802a1841d6406883220b3480dd36ef8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 19 Nov 2017 00:43:58 +0100 Subject: [PATCH 008/291] Finish the shader manager (almost) --- GPU/Common/GPUStateUtils.cpp | 16 +- GPU/GLES/DrawEngineGLES.cpp | 2 +- GPU/GLES/DrawEngineGLES.h | 3 +- GPU/GLES/GPU_GLES.cpp | 6 +- GPU/GLES/ShaderManagerGLES.cpp | 452 ++++++++++------------------ GPU/GLES/ShaderManagerGLES.h | 19 +- GPU/GLES/StateMappingGLES.cpp | 126 +++----- GPU/GLES/TextureCacheGLES.cpp | 27 +- ext/native/thin3d/GLQueueRunner.cpp | 84 +++++- ext/native/thin3d/GLQueueRunner.h | 10 +- ext/native/thin3d/GLRenderManager.h | 65 +++- ext/native/thin3d/thin3d_gl.cpp | 9 +- 12 files changed, 355 insertions(+), 464 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 6060449807..d1091b9a3e 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -576,17 +576,11 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo // This is a bit of a hack as the render buffer isn't always that size // We always scissor on non-buffered so that clears don't spill outside the frame. - if (useBufferedRendering && scissorX1 == 0 && scissorY1 == 0 - && scissorX2 >= (int)gstate_c.curRTWidth - && scissorY2 >= (int)gstate_c.curRTHeight) { - out.scissorEnable = false; - } else { - out.scissorEnable = true; - out.scissorX = renderX + displayOffsetX + scissorX1 * renderWidthFactor; - out.scissorY = renderY + displayOffsetY + scissorY1 * renderHeightFactor; - out.scissorW = (scissorX2 - scissorX1) * renderWidthFactor; - out.scissorH = (scissorY2 - scissorY1) * renderHeightFactor; - } + out.scissorEnable = true; + out.scissorX = renderX + displayOffsetX + scissorX1 * renderWidthFactor; + out.scissorY = renderY + displayOffsetY + scissorY1 * renderHeightFactor; + out.scissorW = (scissorX2 - scissorX1) * renderWidthFactor; + out.scissorH = (scissorY2 - scissorY1) * renderHeightFactor; int curRTWidth = gstate_c.curRTWidth; int curRTHeight = gstate_c.curRTHeight; diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 7cba85b02b..be77ad5362 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -115,7 +115,7 @@ enum { enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MAX = 4 }; -DrawEngineGLES::DrawEngineGLES() : vai_(256) { +DrawEngineGLES::DrawEngineGLES(Draw::DrawContext *draw) : vai_(256), draw_(draw) { decOptions_.expandAllWeightsToFloat = false; decOptions_.expand8BitNormalsToFloat = false; diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 037758d670..f50b0ffb35 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -101,7 +101,7 @@ public: // Handles transform, lighting and drawing. class DrawEngineGLES : public DrawEngineCommon { public: - DrawEngineGLES(); + DrawEngineGLES(Draw::DrawContext *draw); virtual ~DrawEngineGLES(); void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead); @@ -189,6 +189,7 @@ private: TextureCacheGLES *textureCache_ = nullptr; FramebufferManagerGLES *framebufferManager_ = nullptr; FragmentTestCacheGLES *fragmentTestCache_ = nullptr; + Draw::DrawContext *draw_; int bufferDecimationCounter_ = 0; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index b6f112a0ae..78528e7a19 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -79,11 +79,13 @@ static const GLESCommandTableEntry commandTable[] = { GPU_GLES::CommandInfo GPU_GLES::cmdInfo_[256]; GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) -: GPUCommon(gfxCtx, draw) { +: GPUCommon(gfxCtx, draw), drawEngine_(draw) { UpdateVsyncInterval(true); CheckGPUFeatures(); - shaderManagerGL_ = new ShaderManagerGLES(); + GLRenderManager *render = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + + shaderManagerGL_ = new ShaderManagerGLES(render); framebufferManagerGL_ = new FramebufferManagerGLES(draw); framebufferManager_ = framebufferManagerGL_; textureCacheGL_ = new TextureCacheGLES(draw); diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 11ee8d736d..b2a54a3d42 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -26,6 +26,7 @@ #include "base/logging.h" #include "base/timeutil.h" #include "gfx/gl_debug_log.h" +#include "thin3d/GLRenderManager.h" #include "i18n/i18n.h" #include "math/math_util.h" #include "math/lin/matrix4x4.h" @@ -43,8 +44,8 @@ #include "GPU/GLES/DrawEngineGLES.h" #include "FramebufferManagerGLES.h" -Shader::Shader(const ShaderID &id, const char *code, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask) - : failed_(false), useHWTransform_(useHWTransform), attrMask_(attrMask), uniformMask_(uniformMask) { +Shader::Shader(GLRenderManager *render, const char *code, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask) + : render_(render), failed_(false), useHWTransform_(useHWTransform), attrMask_(attrMask), uniformMask_(uniformMask) { PROFILE_THIS_SCOPE("shadercomp"); isFragment_ = glShaderType == GL_FRAGMENT_SHADER; source_ = code; @@ -55,218 +56,131 @@ Shader::Shader(const ShaderID &id, const char *code, uint32_t glShaderType, bool printf("%s\n", code); #endif #endif - shader = glCreateShader(glShaderType); - glShaderSource(shader, 1, &code, 0); - glCompileShader(shader); - GLint success = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - if (!success) { -#define MAX_INFO_LOG_SIZE 2048 - GLchar infoLog[MAX_INFO_LOG_SIZE]; - GLsizei len; - glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog); - infoLog[len] = '\0'; -#ifdef __ANDROID__ - ELOG("Error in shader compilation! %s\n", infoLog); - ELOG("Shader source:\n%s\n", (const char *)code); -#endif - - std::string desc = GetShaderString(SHADER_STRING_SHORT_DESC, id); - ERROR_LOG(G3D, "Error in shader compilation for: %s", desc.c_str()); - ERROR_LOG(G3D, "Info log: %s", infoLog); - ERROR_LOG(G3D, "Shader source:\n%s\n", (const char *)code); - Reporting::ReportMessage("Error in shader compilation: info: %s\n%s\n%s", infoLog, desc.c_str(), (const char *)code); -#ifdef SHADERLOG - OutputDebugStringUTF8(infoLog); -#endif - failed_ = true; - shader = 0; - } else { - DEBUG_LOG(G3D, "Compiled shader:\n%s\n", (const char *)code); - } - CHECK_GL_ERROR_IF_DEBUG(); + shader = render->CreateShader(glShaderType, source_); } Shader::~Shader() { - if (shader) - glDeleteShader(shader); + render_->DeleteShader(shader); } -LinkedShader::LinkedShader(VShaderID VSID, Shader *vs, FShaderID FSID, Shader *fs, bool useHWTransform, bool preloading) - : useHWTransform_(useHWTransform) { +LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, FShaderID FSID, Shader *fs, bool useHWTransform, bool preloading) + : render_(render), useHWTransform_(useHWTransform) { PROFILE_THIS_SCOPE("shaderlink"); - program = glCreateProgram(); vs_ = vs; - glAttachShader(program, vs->shader); - glAttachShader(program, fs->shader); - // Bind attribute locations to fixed locations so that they're - // the same in all shaders. We use this later to minimize the calls to - // glEnableVertexAttribArray and glDisableVertexAttribArray. - glBindAttribLocation(program, ATTR_POSITION, "position"); - glBindAttribLocation(program, ATTR_TEXCOORD, "texcoord"); - glBindAttribLocation(program, ATTR_NORMAL, "normal"); - glBindAttribLocation(program, ATTR_W1, "w1"); - glBindAttribLocation(program, ATTR_W2, "w2"); - glBindAttribLocation(program, ATTR_COLOR0, "color0"); - glBindAttribLocation(program, ATTR_COLOR1, "color1"); + std::vector shaders; + shaders.push_back(vs->shader); + shaders.push_back(fs->shader); -#if !defined(USING_GLES2) - if (gstate_c.Supports(GPU_SUPPORTS_DUALSOURCE_BLEND)) { - // Dual source alpha - glBindFragDataLocationIndexed(program, 0, 0, "fragColor0"); - glBindFragDataLocationIndexed(program, 0, 1, "fragColor1"); - } else if (gl_extensions.VersionGEThan(3, 3, 0)) { - glBindFragDataLocation(program, 0, "fragColor0"); - } -#elif !defined(IOS) - if (gl_extensions.GLES3) { - if (gstate_c.Supports(GPU_SUPPORTS_DUALSOURCE_BLEND)) { - glBindFragDataLocationIndexedEXT(program, 0, 0, "fragColor0"); - glBindFragDataLocationIndexedEXT(program, 0, 1, "fragColor1"); - } - } -#endif - glLinkProgram(program); + std::vector semantics; + semantics.push_back({ ATTR_POSITION, "position" }); + semantics.push_back({ ATTR_TEXCOORD, "texcoord" }); + semantics.push_back({ ATTR_NORMAL, "normal" }); + semantics.push_back({ ATTR_W1, "w1" }); + semantics.push_back({ ATTR_W2, "w2" }); + semantics.push_back({ ATTR_COLOR0, "color0" }); + semantics.push_back({ ATTR_COLOR1, "color1" }); - GLint linkStatus = GL_FALSE; - glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) { - GLint bufLength = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); - if (bufLength) { - char* buf = new char[bufLength]; - glGetProgramInfoLog(program, bufLength, NULL, buf); -#ifdef __ANDROID__ - ELOG("Could not link program:\n %s", buf); -#endif - ERROR_LOG(G3D, "Could not link program:\n %s", buf); + std::vector queries; + queries.push_back({ &u_tex, "tex" }); + queries.push_back({ &u_proj, "u_proj" }); + queries.push_back({ &u_proj_through, "u_proj_through" }); - std::string vs_desc = vs->GetShaderString(SHADER_STRING_SHORT_DESC, VSID); - std::string fs_desc = fs->GetShaderString(SHADER_STRING_SHORT_DESC, FSID); - std::string vs_source = vs->GetShaderString(SHADER_STRING_SOURCE_CODE, VSID); - std::string fs_source = fs->GetShaderString(SHADER_STRING_SOURCE_CODE, FSID); + queries.push_back({ &u_proj, "u_proj" }); + queries.push_back({ &u_proj_through, "u_proj_through" }); + queries.push_back({ &u_texenv, "u_texenv" }); + queries.push_back({ &u_fogcolor, "u_fogcolor" }); + queries.push_back({ &u_fogcoef, "u_fogcoef" }); + queries.push_back({ &u_alphacolorref, "u_alphacolorref" }); + queries.push_back({ &u_alphacolormask, "u_alphacolormask" }); + queries.push_back({ &u_stencilReplaceValue, "u_stencilReplaceValue" }); + queries.push_back({ &u_testtex, "testtex" }); - ERROR_LOG(G3D, "VS desc:\n%s", vs_desc.c_str()); - ERROR_LOG(G3D, "FS desc:\n%s", fs_desc.c_str()); - ERROR_LOG(G3D, "VS:\n%s\n", vs_source.c_str()); - ERROR_LOG(G3D, "FS:\n%s\n", fs_source.c_str()); - if (preloading) { - Reporting::ReportMessage("Error in shader program link during preload: info: %s\nfs: %s\n%s\nvs: %s\n%s", buf, fs_desc.c_str(), fs_source.c_str(), vs_desc.c_str(), vs_source.c_str()); - } else { - Reporting::ReportMessage("Error in shader program link: info: %s\nfs: %s\n%s\nvs: %s\n%s", buf, fs_desc.c_str(), fs_source.c_str(), vs_desc.c_str(), vs_source.c_str()); - } -#ifdef SHADERLOG - OutputDebugStringUTF8(buf); - OutputDebugStringUTF8(vs_source.c_str()); - OutputDebugStringUTF8(fs_source.c_str()); -#endif - delete [] buf; // we're dead! - } - // Prevent a buffer overflow. - numBones = 0; - // Avoid weird attribute enables. - attrMask = 0; - availableUniforms = 0; - return; - } - - INFO_LOG(G3D, "Linked shader: vs %i fs %i", (int)vs->shader, (int)fs->shader); - - u_tex = glGetUniformLocation(program, "tex"); - u_proj = glGetUniformLocation(program, "u_proj"); - u_proj_through = glGetUniformLocation(program, "u_proj_through"); - u_texenv = glGetUniformLocation(program, "u_texenv"); - u_fogcolor = glGetUniformLocation(program, "u_fogcolor"); - u_fogcoef = glGetUniformLocation(program, "u_fogcoef"); - u_alphacolorref = glGetUniformLocation(program, "u_alphacolorref"); - u_alphacolormask = glGetUniformLocation(program, "u_alphacolormask"); - u_stencilReplaceValue = glGetUniformLocation(program, "u_stencilReplaceValue"); - u_testtex = glGetUniformLocation(program, "testtex"); - - u_fbotex = glGetUniformLocation(program, "fbotex"); - u_blendFixA = glGetUniformLocation(program, "u_blendFixA"); - u_blendFixB = glGetUniformLocation(program, "u_blendFixB"); - u_fbotexSize = glGetUniformLocation(program, "u_fbotexSize"); + queries.push_back({ &u_fbotex, "fbotex" }); + queries.push_back({ &u_blendFixA, "u_blendFixA" }); + queries.push_back({ &u_blendFixB, "u_blendFixB" }); + queries.push_back({ &u_fbotexSize, "u_fbotexSize" }); // Transform - u_view = glGetUniformLocation(program, "u_view"); - u_world = glGetUniformLocation(program, "u_world"); - u_texmtx = glGetUniformLocation(program, "u_texmtx"); + queries.push_back({ &u_view, "u_view" }); + queries.push_back({ &u_world, "u_world" }); + queries.push_back({ &u_texmtx, "u_texmtx" }); + if (VSID.Bit(VS_BIT_ENABLE_BONES)) numBones = TranslateNumBones(VSID.Bits(VS_BIT_BONES, 3) + 1); else numBones = 0; - u_depthRange = glGetUniformLocation(program, "u_depthRange"); + queries.push_back({ &u_depthRange, "u_depthRange" }); #ifdef USE_BONE_ARRAY - u_bone = glGetUniformLocation(program, "u_bone"); + queries.push_back({ &u_bone, "u_bone" }); #else + static const char * const boneNames[8] = { "u_bone0", "u_bone1", "u_bone2", "u_bone3", "u_bone4", "u_bone5", "u_bone6", "u_bone7", }; for (int i = 0; i < 8; i++) { - char name[10]; - sprintf(name, "u_bone%i", i); - u_bone[i] = glGetUniformLocation(program, name); + queries.push_back({ &u_bone[i], boneNames[i] }); } #endif // Lighting, texturing - u_ambient = glGetUniformLocation(program, "u_ambient"); - u_matambientalpha = glGetUniformLocation(program, "u_matambientalpha"); - u_matdiffuse = glGetUniformLocation(program, "u_matdiffuse"); - u_matspecular = glGetUniformLocation(program, "u_matspecular"); - u_matemissive = glGetUniformLocation(program, "u_matemissive"); - u_uvscaleoffset = glGetUniformLocation(program, "u_uvscaleoffset"); - u_texclamp = glGetUniformLocation(program, "u_texclamp"); - u_texclampoff = glGetUniformLocation(program, "u_texclampoff"); + queries.push_back({ &u_ambient, "u_ambient" }); + queries.push_back({ &u_matambientalpha, "u_matambientalpha" }); + queries.push_back({ &u_matdiffuse, "u_matdiffuse" }); + queries.push_back({ &u_matspecular, "u_matspecular" }); + queries.push_back({ &u_matemissive, "u_matemissive" }); + queries.push_back({ &u_uvscaleoffset, "u_uvscaleoffset" }); + queries.push_back({ &u_texclamp, "u_texclamp" }); + queries.push_back({ &u_texclampoff, "u_texclampoff" }); for (int i = 0; i < 4; i++) { - char temp[64]; - sprintf(temp, "u_lightpos%i", i); - u_lightpos[i] = glGetUniformLocation(program, temp); - sprintf(temp, "u_lightdir%i", i); - u_lightdir[i] = glGetUniformLocation(program, temp); - sprintf(temp, "u_lightatt%i", i); - u_lightatt[i] = glGetUniformLocation(program, temp); - sprintf(temp, "u_lightangle%i", i); - u_lightangle[i] = glGetUniformLocation(program, temp); - sprintf(temp, "u_lightspotCoef%i", i); - u_lightspotCoef[i] = glGetUniformLocation(program, temp); - sprintf(temp, "u_lightambient%i", i); - u_lightambient[i] = glGetUniformLocation(program, temp); - sprintf(temp, "u_lightdiffuse%i", i); - u_lightdiffuse[i] = glGetUniformLocation(program, temp); - sprintf(temp, "u_lightspecular%i", i); - u_lightspecular[i] = glGetUniformLocation(program, temp); + static const char * const lightPosNames[4] = { "u_lightpos0", "u_lightpos1", "u_lightpos2", "u_lightpos3", }; + queries.push_back({ &u_lightpos[i], lightPosNames[i] }); + static const char * const lightdir_names[4] = { "u_lightdir0", "u_lightdir1", "u_lightdir2", "u_lightdir3", }; + queries.push_back({ &u_lightdir[i], lightdir_names[i] }); + static const char * const lightatt_names[4] = { "u_lightatt0", "u_lightatt1", "u_lightatt2", "u_lightatt3", }; + queries.push_back({ &u_lightatt[i], lightatt_names[i] }); + static const char * const lightangle_names[4] = { "u_lightangle0", "u_lightangle1", "u_lightangle2", "u_lightangle3", }; + queries.push_back({ &u_lightangle[i], lightangle_names[i] }); + + static const char * const lightspotCoef_names[4] = { "u_lightspotCoef0", "u_lightspotCoef1", "u_lightspotCoef2", "u_lightspotCoef3", }; + queries.push_back({ &u_lightspotCoef[i], lightspotCoef_names[i] }); + static const char * const lightambient_names[4] = { "u_lightambient0", "u_lightambient1", "u_lightambient2", "u_lightambient3", }; + queries.push_back({ &u_lightambient[i], lightambient_names[i] }); + static const char * const lightdiffuse_names[4] = { "u_lightdiffuse0", "u_lightdiffuse1", "u_lightdiffuse2", "u_lightdiffuse3", }; + queries.push_back({ &u_lightdiffuse[i], lightdiffuse_names[i] }); + static const char * const lightspecular_names[4] = { "u_lightspecular0", "u_lightspecular1", "u_lightspecular2", "u_lightspecular3", }; + queries.push_back({ &u_lightspecular[i], lightspecular_names[i] }); } // We need to fetch these unconditionally, gstate_c.spline or bezier will not be set if we // create this shader at load time from the shader cache. - u_tess_pos_tex = glGetUniformLocation(program, "u_tess_pos_tex"); - u_tess_tex_tex = glGetUniformLocation(program, "u_tess_tex_tex"); - u_tess_col_tex = glGetUniformLocation(program, "u_tess_col_tex"); - u_spline_count_u = glGetUniformLocation(program, "u_spline_count_u"); - u_spline_count_v = glGetUniformLocation(program, "u_spline_count_v"); - u_spline_type_u = glGetUniformLocation(program, "u_spline_type_u"); - u_spline_type_v = glGetUniformLocation(program, "u_spline_type_v"); + queries.push_back({ &u_tess_pos_tex, "u_tess_pos_tex" }); + queries.push_back({ &u_tess_tex_tex, "u_tess_tex_tex" }); + queries.push_back({ &u_tess_col_tex, "u_tess_col_tex" }); + queries.push_back({ &u_spline_count_u, "u_spline_count_u" }); + queries.push_back({ &u_spline_count_v, "u_spline_count_v" }); + queries.push_back({ &u_spline_type_u, "u_spline_type_u" }); + queries.push_back({ &u_spline_type_v, "u_spline_type_v" }); attrMask = vs->GetAttrMask(); availableUniforms = vs->GetUniformMask() | fs->GetUniformMask(); - glUseProgram(program); + program = render->CreateProgram(shaders, semantics, queries, gstate_c.featureFlags & GPU_SUPPORTS_DUALSOURCE_BLEND); + + render->BindProgram(program); // Default uniform values - glUniform1i(u_tex, 0); - glUniform1i(u_fbotex, 1); - glUniform1i(u_testtex, 2); + render->SetUniformI1(&u_tex, 0); + render->SetUniformI1(&u_fbotex, 1); + render->SetUniformI1(&u_fbotex, 2); if (u_tess_pos_tex != -1) - glUniform1i(u_tess_pos_tex, 4); // Texture unit 4 + render->SetUniformI1(&u_tess_pos_tex, 4); // Texture unit 4 if (u_tess_tex_tex != -1) - glUniform1i(u_tess_tex_tex, 5); // Texture unit 5 + render->SetUniformI1(&u_tess_tex_tex, 5); // Texture unit 5 if (u_tess_col_tex != -1) - glUniform1i(u_tess_col_tex, 6); // Texture unit 6 + render->SetUniformI1(&u_tess_col_tex, 6); // Texture unit 6 // The rest, use the "dirty" mechanism. dirtyUniforms = DIRTY_ALL_UNIFORMS; @@ -274,25 +188,28 @@ LinkedShader::LinkedShader(VShaderID VSID, Shader *vs, FShaderID FSID, Shader *f } LinkedShader::~LinkedShader() { - // Shaders are automatically detached by glDeleteProgram. - glDeleteProgram(program); + render_->DeleteProgram(program); } // Utility -static void SetColorUniform3(int uniform, u32 color) { - float f[4]; - Uint8x4ToFloat4(f, color); - glUniform3fv(uniform, 1, f); +static inline void SetFloatUniform(GLRenderManager *render, GLint *uniform, float value) { + render->SetUniformF(uniform, 1, &value); } -static void SetColorUniform3Alpha(int uniform, u32 color, u8 alpha) { +static inline void SetColorUniform3(GLRenderManager *render, GLint *uniform, u32 color) { + float f[4]; + Uint8x4ToFloat4(f, color); + render->SetUniformF(uniform, 3, f); +} + +static void SetColorUniform3Alpha(GLRenderManager *render, GLint *uniform, u32 color, u8 alpha) { float f[4]; Uint8x3ToFloat4_AlphaUint8(f, color, alpha); - glUniform4fv(uniform, 1, f); + render->SetUniformF(uniform, 4, f); } // This passes colors unscaled (e.g. 0 - 255 not 0 - 1.) -static void SetColorUniform3Alpha255(int uniform, u32 color, u8 alpha) { +static void SetColorUniform3Alpha255(GLRenderManager *render, GLint *uniform, u32 color, u8 alpha) { if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) { const float col[4] = { (float)((color & 0xFF) >> 0) * (1.0f / 255.0f), @@ -300,7 +217,7 @@ static void SetColorUniform3Alpha255(int uniform, u32 color, u8 alpha) { (float)((color & 0xFF0000) >> 16) * (1.0f / 255.0f), (float)alpha * (1.0f / 255.0f) }; - glUniform4fv(uniform, 1, col); + render->SetUniformF(uniform, 4, col); } else { const float col[4] = { (float)((color & 0xFF) >> 0), @@ -308,44 +225,44 @@ static void SetColorUniform3Alpha255(int uniform, u32 color, u8 alpha) { (float)((color & 0xFF0000) >> 16), (float)alpha }; - glUniform4fv(uniform, 1, col); + render->SetUniformF(uniform, 4, col); } } -static void SetColorUniform3iAlpha(int uniform, u32 color, u8 alpha) { +static void SetColorUniform3iAlpha(GLRenderManager *render, GLint *uniform, u32 color, u8 alpha) { const int col[4] = { (int)((color & 0xFF) >> 0), (int)((color & 0xFF00) >> 8), (int)((color & 0xFF0000) >> 16), (int)alpha, }; - glUniform4iv(uniform, 1, col); + render->SetUniformI(uniform, 4, col); } -static void SetColorUniform3ExtraFloat(int uniform, u32 color, float extra) { +static void SetColorUniform3ExtraFloat(GLRenderManager *render, GLint *uniform, u32 color, float extra) { const float col[4] = { ((color & 0xFF)) / 255.0f, ((color & 0xFF00) >> 8) / 255.0f, ((color & 0xFF0000) >> 16) / 255.0f, extra }; - glUniform4fv(uniform, 1, col); + render->SetUniformF(uniform, 4, col); } -static void SetFloat24Uniform3(int uniform, const uint32_t data[3]) { +static void SetFloat24Uniform3(GLRenderManager *render, GLint *uniform, const uint32_t data[3]) { float f[4]; ExpandFloat24x3ToFloat4(f, data); - glUniform3fv(uniform, 1, f); + render->SetUniformF(uniform, 3, f); } -static void SetFloatUniform4(int uniform, float data[4]) { - glUniform4fv(uniform, 1, data); +static void SetFloatUniform4(GLRenderManager *render, GLint *uniform, float data[4]) { + render->SetUniformF(uniform, 4, data); } -static void SetMatrix4x3(int uniform, const float *m4x3) { +static void SetMatrix4x3(GLRenderManager *render, GLint *uniform, const float *m4x3) { float m4x4[16]; ConvertMatrix4x3To4x4(m4x4, m4x3); - glUniformMatrix4fv(uniform, 1, GL_FALSE, m4x4); + render->SetUniformM4x4(uniform, m4x4); } static inline void ScaleProjMatrix(Matrix4x4 &in) { @@ -359,34 +276,12 @@ static inline void ScaleProjMatrix(Matrix4x4 &in) { in.translateAndScale(trans, scale); } -void LinkedShader::use(const VShaderID &VSID, LinkedShader *previous) { - glUseProgram(program); - int enable, disable; - if (previous) { - enable = attrMask & ~previous->attrMask; - disable = (~attrMask) & previous->attrMask; - } else { - enable = attrMask; - disable = ~attrMask; - } - for (int i = 0; i < ATTR_COUNT; i++) { - if (enable & (1 << i)) - glEnableVertexAttribArray(i); - else if (disable & (1 << i)) - glDisableVertexAttribArray(i); - } +void LinkedShader::use(const ShaderID &VSID) { + render_->BindProgram(program); + // Note that we no longer track attr masks here - we do it for the input layouts instead. } -void LinkedShader::stop() { - for (int i = 0; i < ATTR_COUNT; i++) { - if (attrMask & (1 << i)) - glDisableVertexAttribArray(i); - } -} - -void LinkedShader::UpdateUniforms(u32 vertType, const VShaderID &vsid) { - CHECK_GL_ERROR_IF_DEBUG(); - +void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) { u64 dirty = dirtyUniforms & availableUniforms; dirtyUniforms = 0; if (!dirty) @@ -448,7 +343,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const VShaderID &vsid) { ScaleProjMatrix(flippedMatrix); - glUniformMatrix4fv(u_proj, 1, GL_FALSE, flippedMatrix.m); + render_->SetUniformM4x4(&u_proj, flippedMatrix.m); } if (dirty & DIRTY_PROJTHROUGHMATRIX) { @@ -459,19 +354,19 @@ void LinkedShader::UpdateUniforms(u32 vertType, const VShaderID &vsid) { } else { proj_through.setOrtho(0.0f, gstate_c.curRTWidth, gstate_c.curRTHeight, 0.0f, 0.0f, 1.0f); } - glUniformMatrix4fv(u_proj_through, 1, GL_FALSE, proj_through.getReadPtr()); + render_->SetUniformM4x4(&u_proj_through, proj_through.getReadPtr()); } if (dirty & DIRTY_TEXENV) { - SetColorUniform3(u_texenv, gstate.texenvcolor); + SetColorUniform3(render_, &u_texenv, gstate.texenvcolor); } if (dirty & DIRTY_ALPHACOLORREF) { - SetColorUniform3Alpha255(u_alphacolorref, gstate.getColorTestRef(), gstate.getAlphaTestRef() & gstate.getAlphaTestMask()); + SetColorUniform3Alpha255(render_, &u_alphacolorref, gstate.getColorTestRef(), gstate.getAlphaTestRef() & gstate.getAlphaTestMask()); } if (dirty & DIRTY_ALPHACOLORMASK) { - SetColorUniform3iAlpha(u_alphacolormask, gstate.colortestmask, gstate.getAlphaTestMask()); + SetColorUniform3iAlpha(render_, &u_alphacolormask, gstate.colortestmask, gstate.getAlphaTestMask()); } if (dirty & DIRTY_FOGCOLOR) { - SetColorUniform3(u_fogcolor, gstate.fogcolor); + SetColorUniform3(render_, &u_fogcolor, gstate.fogcolor); } if (dirty & DIRTY_FOGCOEF) { float fogcoef[2] = { @@ -494,7 +389,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const VShaderID &vsid) { ERROR_LOG_REPORT_ONCE(fognan, G3D, "Unhandled fog NaN/INF combo: %f %f", fogcoef[0], fogcoef[1]); } #endif - glUniform2fv(u_fogcoef, 1, fogcoef); + render_->SetUniformF(&u_fogcoef, 2, fogcoef); } if (dirty & DIRTY_UVSCALEOFFSET) { @@ -518,7 +413,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const VShaderID &vsid) { uvscaleoff[2] = 0.0f; uvscaleoff[3] = 0.0f; } - glUniform4fv(u_uvscaleoffset, 1, uvscaleoff); + render_->SetUniformF(&u_uvscaleoffset, 4, uvscaleoff); } if ((dirty & DIRTY_TEXCLAMP) && u_texclamp != -1) { @@ -540,21 +435,21 @@ void LinkedShader::UpdateUniforms(u32 vertType, const VShaderID &vsid) { gstate_c.curTextureXOffset * invW, gstate_c.curTextureYOffset * invH, }; - glUniform4fv(u_texclamp, 1, texclamp); + render_->SetUniformF(&u_texclamp, 4, texclamp); if (u_texclampoff != -1) { - glUniform2fv(u_texclampoff, 1, texclampoff); + render_->SetUniformF(&u_texclampoff, 2, texclampoff); } } // Transform if (dirty & DIRTY_WORLDMATRIX) { - SetMatrix4x3(u_world, gstate.worldMatrix); + SetMatrix4x3(render_, &u_world, gstate.worldMatrix); } if (dirty & DIRTY_VIEWMATRIX) { - SetMatrix4x3(u_view, gstate.viewMatrix); + SetMatrix4x3(render_, &u_view, gstate.viewMatrix); } if (dirty & DIRTY_TEXMATRIX) { - SetMatrix4x3(u_texmtx, gstate.tgenMatrix); + SetMatrix4x3(render_, &u_texmtx, gstate.tgenMatrix); } if ((dirty & DIRTY_DEPTHRANGE) && u_depthRange != -1) { // Since depth is [-1, 1] mapping to [minz, maxz], this is easyish. @@ -580,53 +475,27 @@ void LinkedShader::UpdateUniforms(u32 vertType, const VShaderID &vsid) { } float data[4] = { viewZScale, viewZCenter, viewZCenter, viewZInvScale }; - SetFloatUniform4(u_depthRange, data); + SetFloatUniform4(render_, &u_depthRange, data); } if (dirty & DIRTY_STENCILREPLACEVALUE) { - glUniform1f(u_stencilReplaceValue, (float)gstate.getStencilTestRef() * (1.0f / 255.0f)); + float f = (float)gstate.getStencilTestRef() * (1.0f / 255.0f); + render_->SetUniformF(&u_stencilReplaceValue, 1, &f); } - // TODO: Could even set all bones in one go if they're all dirty. -#ifdef USE_BONE_ARRAY - if (u_bone != -1) { - float allBones[8 * 16]; - - bool allDirty = true; - for (int i = 0; i < numBones; i++) { - if (dirty & (DIRTY_BONEMATRIX0 << i)) { - ConvertMatrix4x3To4x4(allBones + 16 * i, gstate.boneMatrix + 12 * i); - } else { - allDirty = false; - } - } - if (allDirty) { - // Set them all with one call - glUniformMatrix4fv(u_bone, numBones, GL_FALSE, allBones); - } else { - // Set them one by one. Could try to coalesce two in a row etc but too lazy. - for (int i = 0; i < numBones; i++) { - if (dirty & (DIRTY_BONEMATRIX0 << i)) { - glUniformMatrix4fv(u_bone + i, 1, GL_FALSE, allBones + 16 * i); - } - } - } - } -#else float bonetemp[16]; for (int i = 0; i < numBones; i++) { if (dirty & (DIRTY_BONEMATRIX0 << i)) { ConvertMatrix4x3To4x4(bonetemp, gstate.boneMatrix + 12 * i); - glUniformMatrix4fv(u_bone[i], 1, GL_FALSE, bonetemp); + render_->SetUniformM4x4(&u_bone[i], bonetemp); } } -#endif if (dirty & DIRTY_SHADERBLEND) { if (u_blendFixA != -1) { - SetColorUniform3(u_blendFixA, gstate.getFixA()); + SetColorUniform3(render_, &u_blendFixA, gstate.getFixA()); } if (u_blendFixB != -1) { - SetColorUniform3(u_blendFixB, gstate.getFixB()); + SetColorUniform3(render_, &u_blendFixB, gstate.getFixB()); } const float fbotexSize[2] = { @@ -634,25 +503,25 @@ void LinkedShader::UpdateUniforms(u32 vertType, const VShaderID &vsid) { 1.0f / (float)gstate_c.curRTRenderHeight, }; if (u_fbotexSize != -1) { - glUniform2fv(u_fbotexSize, 1, fbotexSize); + render_->SetUniformF(&u_fbotexSize, 2, fbotexSize); } } // Lighting if (dirty & DIRTY_AMBIENT) { - SetColorUniform3Alpha(u_ambient, gstate.ambientcolor, gstate.getAmbientA()); + SetColorUniform3Alpha(render_, &u_ambient, gstate.ambientcolor, gstate.getAmbientA()); } if (dirty & DIRTY_MATAMBIENTALPHA) { - SetColorUniform3Alpha(u_matambientalpha, gstate.materialambient, gstate.getMaterialAmbientA()); + SetColorUniform3Alpha(render_, &u_matambientalpha, gstate.materialambient, gstate.getMaterialAmbientA()); } if (dirty & DIRTY_MATDIFFUSE) { - SetColorUniform3(u_matdiffuse, gstate.materialdiffuse); + SetColorUniform3(render_, &u_matdiffuse, gstate.materialdiffuse); } if (dirty & DIRTY_MATEMISSIVE) { - SetColorUniform3(u_matemissive, gstate.materialemissive); + SetColorUniform3(render_, &u_matemissive, gstate.materialemissive); } if (dirty & DIRTY_MATSPECULAR) { - SetColorUniform3ExtraFloat(u_matspecular, gstate.materialspecular, getFloat24(gstate.materialspecularcoef)); + SetColorUniform3ExtraFloat(render_, &u_matspecular, gstate.materialspecular, getFloat24(gstate.materialspecularcoef)); } for (int i = 0; i < 4; i++) { @@ -668,34 +537,33 @@ void LinkedShader::UpdateUniforms(u32 vertType, const VShaderID &vsid) { else len = 1.0f / len; float vec[3] = { x * len, y * len, z * len }; - glUniform3fv(u_lightpos[i], 1, vec); + render_->SetUniformF(&u_lightpos[i], 3, vec); } else { - SetFloat24Uniform3(u_lightpos[i], &gstate.lpos[i * 3]); + SetFloat24Uniform3(render_, &u_lightpos[i], &gstate.lpos[i * 3]); } - if (u_lightdir[i] != -1) SetFloat24Uniform3(u_lightdir[i], &gstate.ldir[i * 3]); - if (u_lightatt[i] != -1) SetFloat24Uniform3(u_lightatt[i], &gstate.latt[i * 3]); - if (u_lightangle[i] != -1) glUniform1f(u_lightangle[i], getFloat24(gstate.lcutoff[i])); - if (u_lightspotCoef[i] != -1) glUniform1f(u_lightspotCoef[i], getFloat24(gstate.lconv[i])); - if (u_lightambient[i] != -1) SetColorUniform3(u_lightambient[i], gstate.lcolor[i * 3]); - if (u_lightdiffuse[i] != -1) SetColorUniform3(u_lightdiffuse[i], gstate.lcolor[i * 3 + 1]); - if (u_lightspecular[i] != -1) SetColorUniform3(u_lightspecular[i], gstate.lcolor[i * 3 + 2]); + if (u_lightdir[i] != -1) SetFloat24Uniform3(render_, &u_lightdir[i], &gstate.ldir[i * 3]); + if (u_lightatt[i] != -1) SetFloat24Uniform3(render_, &u_lightatt[i], &gstate.latt[i * 3]); + if (u_lightangle[i] != -1) SetFloatUniform(render_, &u_lightangle[i], getFloat24(gstate.lcutoff[i])); + if (u_lightspotCoef[i] != -1) SetFloatUniform(render_, &u_lightspotCoef[i], getFloat24(gstate.lconv[i])); + if (u_lightambient[i] != -1) SetColorUniform3(render_, &u_lightambient[i], gstate.lcolor[i * 3]); + if (u_lightdiffuse[i] != -1) SetColorUniform3(render_, &u_lightdiffuse[i], gstate.lcolor[i * 3 + 1]); + if (u_lightspecular[i] != -1) SetColorUniform3(render_, &u_lightspecular[i], gstate.lcolor[i * 3 + 2]); } } if (dirty & DIRTY_BEZIERSPLINE) { - glUniform1i(u_spline_count_u, gstate_c.spline_count_u); + render_->SetUniformI1(&u_spline_count_u, gstate_c.spline_count_u); if (u_spline_count_v != -1) - glUniform1i(u_spline_count_v, gstate_c.spline_count_v); + render_->SetUniformI1(&u_spline_count_v, gstate_c.spline_count_v); if (u_spline_type_u != -1) - glUniform1i(u_spline_type_u, gstate_c.spline_type_u); + render_->SetUniformI1(&u_spline_type_u, gstate_c.spline_type_u); if (u_spline_type_v != -1) - glUniform1i(u_spline_type_v, gstate_c.spline_type_v); + render_->SetUniformI1(&u_spline_type_v, gstate_c.spline_type_v); } - CHECK_GL_ERROR_IF_DEBUG(); } -ShaderManagerGLES::ShaderManagerGLES() - : lastShader_(nullptr), shaderSwitchDirtyUniforms_(0), diskCacheDirty_(false), fsCache_(16), vsCache_(16) { +ShaderManagerGLES::ShaderManagerGLES(GLRenderManager *render) + : render_(render), lastShader_(nullptr), shaderSwitchDirtyUniforms_(0), diskCacheDirty_(false), fsCache_(16), vsCache_(16) { codeBuffer_ = new char[16384]; lastFSID_.set_invalid(); lastVSID_.set_invalid(); @@ -737,8 +605,6 @@ void ShaderManagerGLES::DirtyShader() { } void ShaderManagerGLES::DirtyLastShader() { // disables vertex arrays - if (lastShader_) - lastShader_->stop(); lastShader_ = nullptr; lastVShaderSame_ = false; } @@ -748,7 +614,7 @@ Shader *ShaderManagerGLES::CompileFragmentShader(FShaderID FSID) { if (!GenerateFragmentShader(FSID, codeBuffer_, &uniformMask)) { return nullptr; } - return new Shader(FSID, codeBuffer_, GL_FRAGMENT_SHADER, false, 0, uniformMask); + return new Shader(render_, codeBuffer_, GL_FRAGMENT_SHADER, false, 0, uniformMask); } Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { @@ -756,7 +622,7 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { uint32_t attrMask; uint64_t uniformMask; GenerateVertexShader(VSID, codeBuffer_, &attrMask, &uniformMask); - return new Shader(VSID, codeBuffer_, GL_VERTEX_SHADER, useHWTransform, attrMask, uniformMask); + return new Shader(render_, codeBuffer_, GL_VERTEX_SHADER, useHWTransform, attrMask, uniformMask); } Shader *ShaderManagerGLES::ApplyVertexShader(int prim, u32 vertType, VShaderID *VSID) { @@ -806,7 +672,7 @@ Shader *ShaderManagerGLES::ApplyVertexShader(int prim, u32 vertType, VShaderID * uint32_t attrMask; uint64_t uniformMask; GenerateVertexShader(vsidTemp, codeBuffer_, &attrMask, &uniformMask); - vs = new Shader(vsidTemp, codeBuffer_, GL_VERTEX_SHADER, false, attrMask, uniformMask); + vs = new Shader(render_, codeBuffer_, GL_VERTEX_SHADER, false, attrMask, uniformMask); } vsCache_.Insert(*VSID, vs); @@ -860,12 +726,12 @@ LinkedShader *ShaderManagerGLES::ApplyFragmentShader(VShaderID VSID, Shader *vs, _dbg_assert_(G3D, FSID.Bit(FS_BIT_FLATSHADE) == VSID.Bit(VS_BIT_FLATSHADE)); // Check if we can link these. - ls = new LinkedShader(VSID, vs, FSID, fs, vs->UseHWTransform()); - ls->use(VSID, lastShader_); + ls = new LinkedShader(render_, VSID, vs, FSID, fs, vs->UseHWTransform()); + ls->use(VSID); const LinkedShaderCacheEntry entry(vs, fs, ls); linkedShaderCache_.push_back(entry); } else { - ls->use(VSID, lastShader_); + ls->use(VSID); } ls->UpdateUniforms(vertType, VSID); @@ -1083,7 +949,7 @@ bool ShaderManagerGLES::ContinuePrecompile(float sliceTime) { Shader *vs = vsCache_.Get(vsid); Shader *fs = fsCache_.Get(fsid); if (vs && fs) { - LinkedShader *ls = new LinkedShader(vsid, vs, fsid, fs, vs->UseHWTransform(), true); + LinkedShader *ls = new LinkedShader(render_, vsid, vs, fsid, fs, vs->UseHWTransform(), true); LinkedShaderCacheEntry entry(vs, fs, ls); linkedShaderCache_.push_back(entry); } diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index fe9c0226da..34ab88a7d8 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -21,6 +21,7 @@ #include "base/basictypes.h" #include "Common/Hashmaps.h" +#include "thin3d/GLRenderManager.h" #include "GPU/Common/ShaderCommon.h" #include "GPU/Common/ShaderId.h" #include "GPU/GLES/VertexShaderGeneratorGLES.h" @@ -43,18 +44,18 @@ enum { class LinkedShader { public: - LinkedShader(VShaderID VSID, Shader *vs, FShaderID FSID, Shader *fs, bool useHWTransform, bool preloading = false); + LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, FShaderID FSID, Shader *fs, bool useHWTransform, bool preloading = false); ~LinkedShader(); - void use(const VShaderID &VSID, LinkedShader *previous); - void stop(); - void UpdateUniforms(u32 vertType, const VShaderID &VSID); + void use(const ShaderID &VSID); + void UpdateUniforms(u32 vertType, const ShaderID &VSID); + GLRenderManager *render_; Shader *vs_; // Set to false if the VS failed, happens on Mali-400 a lot for complex shaders. bool useHWTransform_; - uint32_t program = 0; + GLRProgram *program; uint64_t availableUniforms; uint64_t dirtyUniforms = 0; @@ -124,9 +125,9 @@ public: class Shader { public: - Shader(const ShaderID &id, const char *code, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask); + Shader(GLRenderManager *render, const char *code, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask); ~Shader(); - uint32_t shader; + GLRShader *shader; bool Failed() const { return failed_; } bool UseHWTransform() const { return useHWTransform_; } // only relevant for vtx shaders @@ -137,6 +138,7 @@ public: uint64_t GetUniformMask() const { return uniformMask_; } private: + GLRenderManager *render_; std::string source_; bool failed_; bool useHWTransform_; @@ -147,7 +149,7 @@ private: class ShaderManagerGLES : public ShaderManagerCommon { public: - ShaderManagerGLES(); + ShaderManagerGLES(GLRenderManager *render); ~ShaderManagerGLES(); void ClearCache(bool deleteThem); // TODO: deleteThem currently not respected @@ -186,6 +188,7 @@ private: }; typedef std::vector LinkedShaderCache; + GLRenderManager *render_; LinkedShaderCache linkedShaderCache_; bool lastVShaderSame_; diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index 195c21d1b9..f810087770 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -23,6 +23,7 @@ #include "StateMappingGLES.h" #include "profiler/profiler.h" #include "gfx/gl_debug_log.h" +#include "thin3d/GLRenderManager.h" #include "GPU/Math3D.h" #include "GPU/GPUState.h" @@ -123,14 +124,15 @@ static const GLushort logicOps[] = { inline void DrawEngineGLES::ResetShaderBlending() { if (fboTexBound_) { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); + GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + renderManager->BindTexture(1, nullptr); fboTexBound_ = false; } } void DrawEngineGLES::ApplyDrawState(int prim) { + GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) { textureCache_->SetTexture(); gstate_c.Clean(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); @@ -163,11 +165,10 @@ void DrawEngineGLES::ApplyDrawState(int prim) { gstate_c.SetAllowShaderBlend(!g_Config.bDisableSlowFramebufEffects); if (gstate.isModeClear()) { - glstate.blend.disable(); // Color Test bool colorMask = gstate.isClearModeColorMask(); bool alphaMask = gstate.isClearModeAlphaMask(); - glstate.colorMask.set(colorMask, colorMask, colorMask, alphaMask); + renderManager->SetNoBlendAndMask((colorMask ? 7 : 0) | (alphaMask ? 8 : 0)); #ifndef USING_GLES2 if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { // Logic Ops @@ -194,11 +195,6 @@ void DrawEngineGLES::ApplyDrawState(int prim) { } if (blendState.enabled) { - glstate.blend.enable(); - glstate.blendEquationSeparate.set(glBlendEqLookup[(size_t)blendState.eqColor], glBlendEqLookup[(size_t)blendState.eqAlpha]); - glstate.blendFuncSeparate.set( - glBlendFactorLookup[(size_t)blendState.srcColor], glBlendFactorLookup[(size_t)blendState.dstColor], - glBlendFactorLookup[(size_t)blendState.srcAlpha], glBlendFactorLookup[(size_t)blendState.dstAlpha]); if (blendState.dirtyShaderBlend) { gstate_c.Dirty(DIRTY_SHADERBLEND); } @@ -210,10 +206,8 @@ void DrawEngineGLES::ApplyDrawState(int prim) { (float)((color & 0xFF0000) >> 16) * (1.0f / 255.0f), (float)((color & 0xFF000000) >> 24) * (1.0f / 255.0f), }; - glstate.blendColor.set(col); + renderManager->SetBlendFactor(col); } - } else { - glstate.blend.disable(); } // PSP color/alpha mask is per bit but we can only support per byte. @@ -235,18 +229,21 @@ void DrawEngineGLES::ApplyDrawState(int prim) { WARN_LOG_REPORT_ONCE(amask, G3D, "Unsupported alpha/stencil mask: %02x", abits); } #endif - - glstate.colorMask.set(rmask, gmask, bmask, amask); + int mask = (int)rmask | ((int)gmask << 1) | ((int)bmask << 2) | ((int)amask << 3); + renderManager->SetBlendAndMask(mask, blendState.enabled, + glBlendFactorLookup[(size_t)blendState.srcColor], glBlendFactorLookup[(size_t)blendState.dstColor], + glBlendFactorLookup[(size_t)blendState.srcAlpha], glBlendFactorLookup[(size_t)blendState.dstAlpha], + glBlendEqLookup[(size_t)blendState.eqColor], glBlendEqLookup[(size_t)blendState.eqAlpha]); #ifndef USING_GLES2 if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { // TODO: Make this dynamic // Logic Ops if (gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_COPY) { - glstate.colorLogicOp.enable(); - glstate.logicOp.set(logicOps[gstate.getLogicOp()]); + //glstate.colorLogicOp.enable(); + //glstate.logicOp.set(logicOps[gstate.getLogicOp()]); } else { - glstate.colorLogicOp.disable(); + //glstate.colorLogicOp.disable(); } } #endif @@ -257,26 +254,18 @@ void DrawEngineGLES::ApplyDrawState(int prim) { gstate_c.Clean(DIRTY_RASTER_STATE); // Dither - if (gstate.isDitherEnabled()) { - glstate.dither.enable(); - glstate.dither.set(true); - } else { - glstate.dither.disable(); - } + bool dither = gstate.isDitherEnabled(); + bool cullEnable; + GLenum cullMode = cullingMode[gstate.getCullMode() ^ !useBufferedRendering]; if (gstate.isModeClear()) { // Culling - glstate.cullFace.disable(); + cullEnable = false; } else { // Set cull - bool cullEnabled = !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); - if (cullEnabled) { - glstate.cullFace.enable(); - glstate.cullFaceMode.set(cullingMode[gstate.getCullMode() ^ !useBufferedRendering]); - } else { - glstate.cullFace.disable(); - } + cullEnable = !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); } + renderManager->SetRaster(cullEnable, GL_CCW, cullMode, dither); } if (gstate_c.IsDirty(DIRTY_DEPTHSTENCIL_STATE)) { @@ -284,51 +273,24 @@ void DrawEngineGLES::ApplyDrawState(int prim) { bool enableStencilTest = !g_Config.bDisableStencilTest; if (gstate.isModeClear()) { // Depth Test - glstate.depthTest.enable(); - glstate.depthFunc.set(GL_ALWAYS); - glstate.depthWrite.set(gstate.isClearModeDepthMask() ? GL_TRUE : GL_FALSE); if (gstate.isClearModeDepthMask()) { framebufferManager_->SetDepthUpdated(); } - - // Stencil Test - if (gstate.isClearModeAlphaMask() && enableStencilTest) { - glstate.stencilTest.enable(); - glstate.stencilOp.set(GL_REPLACE, GL_REPLACE, GL_REPLACE); - // TODO: In clear mode, the stencil value is set to the alpha value of the vertex. - // A normal clear will be 2 points, the second point has the color. - // We should set "ref" to that value instead of 0. - // In case of clear rectangles, we set it again once we know what the color is. - glstate.stencilFunc.set(GL_ALWAYS, 255, 0xFF); - glstate.stencilMask.set(0xFF); - } else { - glstate.stencilTest.disable(); - } + renderManager->SetStencil(gstate.isClearModeAlphaMask() && enableStencilTest, GL_ALWAYS, GL_REPLACE, GL_REPLACE, GL_REPLACE, 0xFF, 0xFF, 0xFF); + renderManager->SetDepth(true, gstate.isClearModeDepthMask() ? true : false, GL_ALWAYS); } else { // Depth Test - if (gstate.isDepthTestEnabled()) { - glstate.depthTest.enable(); - glstate.depthFunc.set(compareOps[gstate.getDepthTestFunction()]); - glstate.depthWrite.set(gstate.isDepthWriteEnabled() ? GL_TRUE : GL_FALSE); - if (gstate.isDepthWriteEnabled()) { - framebufferManager_->SetDepthUpdated(); - } - } else { - glstate.depthTest.disable(); + renderManager->SetDepth(gstate.isDepthTestEnabled(), gstate.isDepthWriteEnabled(), compareOps[gstate.getDepthTestFunction()]); + if (gstate.isDepthTestEnabled() && gstate.isDepthWriteEnabled()) { + framebufferManager_->SetDepthUpdated(); } GenericStencilFuncState stencilState; ConvertStencilFuncState(stencilState); - // Stencil Test - if (stencilState.enabled) { - glstate.stencilTest.enable(); - glstate.stencilFunc.set(compareOps[stencilState.testFunc], stencilState.testRef, stencilState.testMask); - glstate.stencilOp.set(stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass]); - glstate.stencilMask.set(stencilState.writeMask); - } else { - glstate.stencilTest.disable(); - } + renderManager->SetStencil(stencilState.enabled, compareOps[stencilState.testFunc], + stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass], + stencilState.writeMask, stencilState.testMask, stencilState.testRef); } } @@ -340,21 +302,18 @@ void DrawEngineGLES::ApplyDrawState(int prim) { framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); - if (vpAndScissor.scissorEnable) { - glstate.scissorTest.enable(); - if (!useBufferedRendering) { - vpAndScissor.scissorY = PSP_CoreParameter().pixelHeight - vpAndScissor.scissorH - vpAndScissor.scissorY; - } - glstate.scissorRect.set(vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH); - } else { - glstate.scissorTest.disable(); + if (!useBufferedRendering) { + vpAndScissor.scissorY = PSP_CoreParameter().pixelHeight - vpAndScissor.scissorH - vpAndScissor.scissorY; } + renderManager->SetScissor(GLRect2D{ vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH }); if (!useBufferedRendering) { vpAndScissor.viewportY = PSP_CoreParameter().pixelHeight - vpAndScissor.viewportH - vpAndScissor.viewportY; } - glstate.viewport.set(vpAndScissor.viewportX, vpAndScissor.viewportY, vpAndScissor.viewportW, vpAndScissor.viewportH); - glstate.depthRange.set(vpAndScissor.depthRangeMin, vpAndScissor.depthRangeMax); + renderManager->SetViewport({ + vpAndScissor.viewportX, vpAndScissor.viewportY, + vpAndScissor.viewportW, vpAndScissor.viewportH, + vpAndScissor.depthRangeMin, vpAndScissor.depthRangeMax }); if (vpAndScissor.dirtyProj) { gstate_c.Dirty(DIRTY_PROJMATRIX); @@ -363,7 +322,6 @@ void DrawEngineGLES::ApplyDrawState(int prim) { gstate_c.Dirty(DIRTY_DEPTHRANGE); } } - CHECK_GL_ERROR_IF_DEBUG(); } void DrawEngineGLES::ApplyDrawStateLate() { @@ -371,32 +329,20 @@ void DrawEngineGLES::ApplyDrawStateLate() { // TODO: Set the nearest/linear here (since we correctly know if alpha/color tests are needed)? if (!gstate.isModeClear()) { if (fboTexNeedBind_) { - CHECK_GL_ERROR_IF_DEBUG(); // Note that this is positions, not UVs, that we need the copy from. framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY); framebufferManager_->RebindFramebuffer(); - CHECK_GL_ERROR_IF_DEBUG(); - - glActiveTexture(GL_TEXTURE1); - // If we are rendering at a higher resolution, linear is probably best for the dest color. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glActiveTexture(GL_TEXTURE0); fboTexBound_ = true; fboTexNeedBind_ = false; - CHECK_GL_ERROR_IF_DEBUG(); } - CHECK_GL_ERROR_IF_DEBUG(); // Apply the texture after the FBO tex, since it might unbind the texture. // TODO: Could use a separate texture unit to be safer? textureCache_->ApplyTexture(); - CHECK_GL_ERROR_IF_DEBUG(); // Apply last, once we know the alpha params of the texture. if (gstate.isAlphaTestEnabled() || gstate.isColorTestEnabled()) { fragmentTestCache_->BindTestTexture(GL_TEXTURE2); } - CHECK_GL_ERROR_IF_DEBUG(); } } diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index f9daf9faef..430d4368b3 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -164,25 +164,14 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { } } - if (force || entry.minFilt != minFilt) { + if (force || entry.minFilt != minFilt || entry.magFilt != magFilt || entry.sClamp != sClamp || entry.tClamp != tClamp) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFiltGL[minFilt]); - entry.minFilt = minFilt; - } - if (force || entry.magFilt != magFilt) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFiltGL[magFilt]); - entry.magFilt = magFilt; - } - - if (entry.framebuffer) { - WARN_LOG_REPORT_ONCE(wrongFramebufAttach, G3D, "Framebuffer still attached in UpdateSamplingParams()?"); - } - - if (force || entry.sClamp != sClamp) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - entry.sClamp = sClamp; - } - if (force || entry.tClamp != tClamp) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + entry.minFilt = minFilt; + entry.magFilt = magFilt; + entry.sClamp = sClamp; entry.tClamp = tClamp; } CHECK_GL_ERROR_IF_DEBUG(); @@ -201,6 +190,8 @@ void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferH glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFiltGL[minFilt]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFiltGL[magFilt]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); // Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case. // This happens whether we have OES_texture_npot or not. @@ -209,9 +200,6 @@ void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferH if (w != bufferWidth || h != bufferHeight) { return; } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); } static void ConvertColors(void *dstBuf, const void *srcBuf, GLuint dstFmt, int numPixels) { @@ -336,14 +324,11 @@ bool SetDebugTexture() { #endif void TextureCacheGLES::BindTexture(TexCacheEntry *entry) { - CHECK_GL_ERROR_IF_DEBUG(); if (entry->textureName != lastBoundTexture) { glBindTexture(GL_TEXTURE_2D, entry->textureName); lastBoundTexture = entry->textureName; } - CHECK_GL_ERROR_IF_DEBUG(); UpdateSamplingParams(*entry, false); - CHECK_GL_ERROR_IF_DEBUG(); } void TextureCacheGLES::Unbind() { diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 03c6404fa9..c186ea065d 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -53,6 +53,24 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { for (auto iter : program->semantics_) { glBindAttribLocation(program->program, iter.location, iter.attrib); } + +#if !defined(USING_GLES2) + if (step.create_program.support_dual_source) { + // Dual source alpha + glBindFragDataLocationIndexed(program->program, 0, 0, "fragColor0"); + glBindFragDataLocationIndexed(program->program, 0, 1, "fragColor1"); + } else if (gl_extensions.VersionGEThan(3, 3, 0)) { + glBindFragDataLocation(program->program, 0, "fragColor0"); + } +#elif !defined(IOS) + if (gl_extensions.GLES3) { + if (gstate_c.featureFlags & GPU_SUPPORTS_DUALSOURCE_BLEND) { + glBindFragDataLocationIndexedEXT(program->program, 0, 0, "fragColor0"); + glBindFragDataLocationIndexedEXT(program->program, 0, 1, "fragColor1"); + } + } +#endif + glLinkProgram(program->program); GLint linkStatus = GL_FALSE; @@ -86,6 +104,13 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { } } + // Query all the uniforms. + for (int i = 0; i < program->queries_.size(); i++) { + auto &x = program->queries_[i]; + assert(x.name); + *x.dest = glGetUniformLocation(program->program, x.name); + } + // Here we could (using glGetAttribLocation) save a bitmask about which pieces of vertex data are used in the shader // and then AND it with the vertex format bitmask later... } @@ -193,6 +218,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { GLRProgram *curProgram = nullptr; GLint activeTexture = GL_TEXTURE0; + int attrMask = 0; + auto &commands = step.commands; for (const auto &c : commands) { switch (c.cmd) { @@ -245,7 +272,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { break; case GLRRenderCommand::UNIFORM4F: { - int loc = c.uniform4.loc; + int loc = c.uniform4.loc ? *c.uniform4.loc : -1; if (c.uniform4.name) { loc = curProgram->GetUniformLoc(c.uniform4.name); } @@ -267,9 +294,33 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } break; } + case GLRRenderCommand::UNIFORM4I: + { + int loc = c.uniform4.loc ? *c.uniform4.loc : -1; + if (c.uniform4.name) { + loc = curProgram->GetUniformLoc(c.uniform4.name); + } + if (loc >= 0) { + switch (c.uniform4.count) { + case 1: + glUniform1iv(loc, 1, (GLint *)&c.uniform4.v[0]); + break; + case 2: + glUniform2iv(loc, 1, (GLint *)c.uniform4.v); + break; + case 3: + glUniform3iv(loc, 1, (GLint *)c.uniform4.v); + break; + case 4: + glUniform4iv(loc, 1, (GLint *)c.uniform4.v); + break; + } + } + break; + } case GLRRenderCommand::UNIFORMMATRIX: { - int loc = c.uniform4.loc; + int loc = c.uniform4.loc ? *c.uniform4.loc : -1; if (c.uniform4.name) { loc = curProgram->GetUniformLoc(c.uniform4.name); } @@ -302,10 +353,16 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { case GLRRenderCommand::BIND_INPUT_LAYOUT: { GLRInputLayout *layout = c.inputLayout.inputLayout; + int enable, disable; + enable = layout->semanticsMask_ & ~attrMask; + disable = (~layout->semanticsMask_) & attrMask; for (int i = 0; i < 7; i++) { // SEM_MAX - if (layout->semanticsMask_ & (1 << i)) { + if (enable & (1 << i)) { glEnableVertexAttribArray(i); } + if (disable & (1 << i)) { + glDisableVertexAttribArray(i); + } } for (int i = 0; i < layout->entries.size(); i++) { auto &entry = layout->entries[i]; @@ -319,16 +376,6 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glBindBuffer(GL_ARRAY_BUFFER, buf); break; } - case GLRRenderCommand::UNBIND_INPUT_LAYOUT: - { - GLRInputLayout *layout = c.inputLayout.inputLayout; - for (int i = 0; i < 7; i++) { // SEM_MAX - if (layout->semanticsMask_ & (1 << i)) { - glDisableVertexAttribArray(i); - } - } - break; - } case GLRRenderCommand::GENMIPS: glGenerateMipmap(GL_TEXTURE_2D); break; @@ -354,6 +401,11 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } else { glDisable(GL_CULL_FACE); } + if (c.raster.ditherEnable) { + glEnable(GL_DITHER); + } else { + glDisable(GL_DITHER); + } break; default: Crash(); @@ -361,6 +413,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } } + for (int i = 0; i < 7; i++) { + if (attrMask & (1 << i)) { + glDisableVertexAttribArray(i); + } + } + if (activeTexture != GL_TEXTURE0) glActiveTexture(GL_TEXTURE0); glBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index ccd07a3c17..f3d5c7df17 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -31,6 +31,7 @@ enum class GLRRenderCommand : uint8_t { STENCIL, BLEND, BLENDCOLOR, + UNIFORM4I, UNIFORM4F, UNIFORMMATRIX, TEXTURESAMPLER, @@ -43,13 +44,14 @@ enum class GLRRenderCommand : uint8_t { BIND_FB_TEXTURE, BIND_INPUT_LAYOUT, BIND_VERTEX_BUFFER, - UNBIND_INPUT_LAYOUT, GENMIPS, DRAW, DRAW_INDEXED, PUSH_CONSTANTS, }; +// TODO: Bloated since the biggest struct decides the size. Will need something more efficient (separate structs with shared +// type field, smashed right after each other?) struct GLRRenderData { GLRRenderCommand cmd; union { @@ -96,13 +98,13 @@ struct GLRRenderData { } drawIndexed; struct { const char *name; // if null, use loc - GLint loc; + GLint *loc; // NOTE: This is a pointer so we can immediately use things that are "queried" during program creation. GLint count; float v[4]; } uniform4; struct { const char *name; // if null, use loc - GLint loc; + GLint *loc; float m[16]; } uniformMatrix4; struct { @@ -146,6 +148,7 @@ struct GLRRenderData { GLboolean cullEnable; GLenum frontFace; GLenum cullFace; + GLboolean ditherEnable; } raster; }; }; @@ -185,6 +188,7 @@ struct GLRInitStep { GLRProgram *program; GLRShader *shaders[3]; int num_shaders; + bool support_dual_source; } create_program; struct { GLRBuffer *buffer; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index b1559fb697..cd77d12152 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -83,8 +83,15 @@ public: int location; const char *attrib; }; + + struct UniformLocQuery { + GLint *dest; + const char *name; + }; + GLuint program = 0; std::vector semantics_; + std::vector queries_; struct UniformInfo { int loc_; @@ -196,10 +203,10 @@ public: return step.create_texture.texture; } - GLRBuffer *CreateBuffer(GLuint target, int size, GLuint usage) { + GLRBuffer *CreateBuffer(GLuint target, size_t size, GLuint usage) { GLRInitStep step{ GLRInitStepType::CREATE_BUFFER }; step.create_buffer.buffer = new GLRBuffer(target); - step.create_buffer.size = size; + step.create_buffer.size = (int)size; step.create_buffer.usage = usage; initSteps_.push_back(step); return step.create_buffer.buffer; @@ -215,14 +222,23 @@ public: return step.create_shader.shader; } - GLRProgram *CreateProgram(std::vector shaders, std::vector semantics) { + GLRProgram *CreateProgram(std::vector shaders, std::vector semantics, std::vector queries, bool supportDualSource) { GLRInitStep step{ GLRInitStepType::CREATE_PROGRAM }; assert(shaders.size() <= ARRAY_SIZE(step.create_program.shaders)); step.create_program.program = new GLRProgram(); step.create_program.program->semantics_ = semantics; + step.create_program.program->queries_ = queries; for (int i = 0; i < shaders.size(); i++) { step.create_program.shaders[i] = shaders[i]; } +#ifdef _DEBUG + for (auto &iter : queries) { + assert(iter.name); + } + for (auto &sem : semantics) { + assert(sem.attrib); + } +#endif step.create_program.num_shaders = (int)shaders.size(); initSteps_.push_back(step); return step.create_program.program; @@ -320,14 +336,6 @@ public: curRenderStep_->commands.push_back(data); } - void UnbindInputLayout(GLRInputLayout *inputLayout) { - _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - assert(inputLayout); - GLRRenderData data{ GLRRenderCommand::UNBIND_INPUT_LAYOUT }; - data.inputLayout.inputLayout = inputLayout; - curRenderStep_->commands.push_back(data); - } - void GenerateMipmap() { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::GENMIPS }; @@ -357,7 +365,25 @@ public: curRenderStep_->commands.push_back(data); } - void SetUniformF(int loc, int count, const float *udata) { + void SetUniformI(GLint *loc, int count, const int *udata) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::UNIFORM4I }; + data.uniform4.loc = loc; + data.uniform4.count = count; + memcpy(data.uniform4.v, udata, sizeof(int) * count); + curRenderStep_->commands.push_back(data); + } + + void SetUniformI1(GLint *loc, int udata) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::UNIFORM4I }; + data.uniform4.loc = loc; + data.uniform4.count = 1; + memcpy(data.uniform4.v, &udata, sizeof(udata)); + curRenderStep_->commands.push_back(data); + } + + void SetUniformF(GLint *loc, int count, const float *udata) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; data.uniform4.loc = loc; @@ -375,7 +401,7 @@ public: curRenderStep_->commands.push_back(data); } - void SetUniformM4x4(int loc, const float *udata) { + void SetUniformM4x4(GLint *loc, const float *udata) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; data.uniformMatrix4.loc = loc; @@ -405,6 +431,14 @@ public: curRenderStep_->commands.push_back(data); } + void SetNoBlendAndMask(int colorMask) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::BLEND }; + data.blend.mask = colorMask; + data.blend.enabled = false; + curRenderStep_->commands.push_back(data); + } + void SetStencil(bool enabled, GLenum func, GLenum sFail, GLenum zFail, GLenum pass, uint8_t writeMask, uint8_t compareMask, uint8_t refValue) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::STENCIL }; @@ -418,19 +452,20 @@ public: curRenderStep_->commands.push_back(data); } - void SetBlendFactor(float color[4]) { + void SetBlendFactor(const float color[4]) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::BLENDCOLOR }; CopyFloat4(data.blendColor.color, color); curRenderStep_->commands.push_back(data); } - void SetRaster(GLboolean cullEnable, GLenum frontFace, GLenum cullFace) { + void SetRaster(GLboolean cullEnable, GLenum frontFace, GLenum cullFace, GLboolean ditherEnable) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::RASTER }; data.raster.cullEnable = cullEnable; data.raster.frontFace = frontFace; data.raster.cullFace = cullFace; + data.raster.ditherEnable = ditherEnable; curRenderStep_->commands.push_back(data); } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 5d3004d3ba..6ba2d06b38 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -214,7 +214,7 @@ public: class OpenGLRasterState : public RasterState { public: void Apply(GLRenderManager *render) { - render->SetRaster(cullEnable, frontFace, cullMode); + render->SetRaster(cullEnable, frontFace, cullMode, false); } GLboolean cullEnable; @@ -1098,7 +1098,8 @@ bool OpenGLPipeline::LinkShaders() { semantics.push_back({ SEM_NORMAL, "Normal" }); semantics.push_back({ SEM_TANGENT, "Tangent" }); semantics.push_back({ SEM_BINORMAL, "Binormal" }); - program_ = render_->CreateProgram(linkShaders, semantics); + std::vector queries; + program_ = render_->CreateProgram(linkShaders, semantics, queries, false); return true; } @@ -1134,8 +1135,6 @@ void OpenGLContext::Draw(int vertexCount, int offset) { ApplySamplers(); renderManager_.Draw(curPipeline_->prim, offset, vertexCount); - - renderManager_.UnbindInputLayout(curPipeline_->inputLayout->inputLayout_); } void OpenGLContext::DrawIndexed(int vertexCount, int offset) { @@ -1146,7 +1145,6 @@ void OpenGLContext::DrawIndexed(int vertexCount, int offset) { curIBuffer_->Bind(curIBufferOffset_); renderManager_.DrawIndexed(curPipeline_->prim, vertexCount, GL_UNSIGNED_INT, (void *)(intptr_t)offset); - renderManager_.UnbindInputLayout(curPipeline_->inputLayout->inputLayout_); } void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { @@ -1165,7 +1163,6 @@ void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, (void *)offset); renderManager_.Draw(curPipeline_->prim, 0, vertexCount); - renderManager_.UnbindInputLayout(curPipeline_->inputLayout->inputLayout_); renderManager_.BindVertexBuffer(nullptr); #else ApplySamplers(); From 376d92fcc9685b48f5f06258802668ad99f03e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 19 Nov 2017 12:25:57 +0100 Subject: [PATCH 009/291] Start messing with the draw engine... --- GPU/Common/FramebufferCommon.cpp | 1 + GPU/GLES/DrawEngineGLES.cpp | 174 +++++++++++++++++--------- GPU/GLES/DrawEngineGLES.h | 22 ++++ GPU/GLES/FramebufferManagerGLES.cpp | 4 +- GPU/GLES/FramebufferManagerGLES.h | 3 + GPU/GLES/GPU_GLES.cpp | 10 ++ GPU/GLES/GPU_GLES.h | 1 + GPU/GLES/ShaderManagerGLES.cpp | 22 ++-- GPU/GLES/StateMappingGLES.cpp | 22 ++-- ext/native/thin3d/GLQueueRunner.cpp | 24 +++- ext/native/thin3d/GLQueueRunner.h | 1 + ext/native/thin3d/GLRenderManager.cpp | 8 ++ ext/native/thin3d/GLRenderManager.h | 38 ++++-- ext/native/thin3d/thin3d_gl.cpp | 3 +- 14 files changed, 239 insertions(+), 94 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 94072a85b2..a54e58c61e 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -208,6 +208,7 @@ void FramebufferManagerCommon::SetNumExtraFBOs(int num) { extraFBOs_.push_back(fbo); } currentRenderVfb_ = 0; + // TODO: Should probably not do this bind. if (num != 0) draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index be77ad5362..d05489dd92 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -115,7 +115,8 @@ enum { enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MAX = 4 }; -DrawEngineGLES::DrawEngineGLES(Draw::DrawContext *draw) : vai_(256), draw_(draw) { +DrawEngineGLES::DrawEngineGLES(Draw::DrawContext *draw) : vai_(256), draw_(draw), inputLayoutMap_(16) { + render_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); decOptions_.expandAllWeightsToFloat = false; decOptions_.expand8BitNormalsToFloat = false; @@ -178,9 +179,29 @@ void DrawEngineGLES::InitDeviceObjects() { } else { ERROR_LOG(G3D, "Device objects already initialized!"); } + + for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { + frameData_[i].pushVertex = new GLPushBuffer(render_, 1024 * 1024); + frameData_[i].pushIndex = new GLPushBuffer(render_, 512 * 1024); + } + + int vertexSize = sizeof(TransformedVertex); + std::vector entries; + entries.push_back({ ATTR_POSITION, 4, GL_FLOAT, GL_FALSE, vertexSize, 0 }); + entries.push_back({ ATTR_TEXCOORD, 3, GL_FLOAT, GL_FALSE, vertexSize, offsetof(TransformedVertex, u) }); + entries.push_back({ ATTR_COLOR0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, offsetof(TransformedVertex, color0) }); + entries.push_back({ ATTR_COLOR1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, offsetof(TransformedVertex, color1) }); + softwareInputLayout_ = render_->CreateInputLayout(entries); } void DrawEngineGLES::DestroyDeviceObjects() { + for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { + frameData_[i].pushVertex->Destroy(); + frameData_[i].pushIndex->Destroy(); + delete frameData_[i].pushVertex; + delete frameData_[i].pushIndex; + } + ClearTrackedVertexArrays(); if (!bufferNameCache_.empty()) { glstate.arrayBuffer.unbind(); @@ -194,6 +215,27 @@ void DrawEngineGLES::DestroyDeviceObjects() { glDeleteVertexArrays(1, &sharedVao_); } } + + render_->DeleteInputLayout(softwareInputLayout_); +} + +void DrawEngineGLES::ClearInputLayoutMap() { + inputLayoutMap_.Iterate([&](const uint32_t &key, GLRInputLayout *il) { + render_->DeleteInputLayout(il); + }); + inputLayoutMap_.Clear(); +} + +void DrawEngineGLES::BeginFrame() { + FrameData &frameData = frameData_[render_->GetCurFrame()]; + frameData.pushIndex->Begin(); + frameData.pushVertex->Begin(); +} + +void DrawEngineGLES::EndFrame() { + FrameData &frameData = frameData_[render_->GetCurFrame()]; + frameData.pushIndex->End(); + frameData.pushVertex->End(); } struct GlTypeInfo { @@ -220,24 +262,40 @@ static const GlTypeInfo GLComp[] = { {GL_UNSIGNED_SHORT, 4, GL_TRUE},// DEC_U16_4, }; -static inline void VertexAttribSetup(int attrib, int fmt, int stride, u8 *ptr) { +static inline void VertexAttribSetup(int attrib, int fmt, int stride, int offset, std::vector &entries) { if (fmt) { const GlTypeInfo &type = GLComp[fmt]; - glVertexAttribPointer(attrib, type.count, type.type, type.normalized, stride, ptr); + GLRInputLayout::Entry entry; + entry.offset = offset; + entry.location = attrib; + entry.normalized = type.normalized; + entry.type = type.type; + entry.stride = stride; + entry.count = type.count; + entries.push_back(entry); } } // TODO: Use VBO and get rid of the vertexData pointers - with that, we will supply only offsets -static void SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt, u8 *vertexData) { - CHECK_GL_ERROR_IF_DEBUG(); - VertexAttribSetup(ATTR_W1, decFmt.w0fmt, decFmt.stride, vertexData + decFmt.w0off); - VertexAttribSetup(ATTR_W2, decFmt.w1fmt, decFmt.stride, vertexData + decFmt.w1off); - VertexAttribSetup(ATTR_TEXCOORD, decFmt.uvfmt, decFmt.stride, vertexData + decFmt.uvoff); - VertexAttribSetup(ATTR_COLOR0, decFmt.c0fmt, decFmt.stride, vertexData + decFmt.c0off); - VertexAttribSetup(ATTR_COLOR1, decFmt.c1fmt, decFmt.stride, vertexData + decFmt.c1off); - VertexAttribSetup(ATTR_NORMAL, decFmt.nrmfmt, decFmt.stride, vertexData + decFmt.nrmoff); - VertexAttribSetup(ATTR_POSITION, decFmt.posfmt, decFmt.stride, vertexData + decFmt.posoff); - CHECK_GL_ERROR_IF_DEBUG(); +GLRInputLayout *DrawEngineGLES::SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt) { + uint32_t key = decFmt.id; + GLRInputLayout *inputLayout = inputLayoutMap_.Get(key); + if (inputLayout) { + return inputLayout; + } + + std::vector entries; + VertexAttribSetup(ATTR_W1, decFmt.w0fmt, decFmt.stride, decFmt.w0off, entries); + VertexAttribSetup(ATTR_W2, decFmt.w1fmt, decFmt.stride, decFmt.w1off, entries); + VertexAttribSetup(ATTR_TEXCOORD, decFmt.uvfmt, decFmt.stride, decFmt.uvoff, entries); + VertexAttribSetup(ATTR_COLOR0, decFmt.c0fmt, decFmt.stride, decFmt.c0off, entries); + VertexAttribSetup(ATTR_COLOR1, decFmt.c1fmt, decFmt.stride, decFmt.c1off, entries); + VertexAttribSetup(ATTR_NORMAL, decFmt.nrmfmt, decFmt.stride, decFmt.nrmoff, entries); + VertexAttribSetup(ATTR_POSITION, decFmt.posfmt, decFmt.stride, decFmt.posoff, entries); + + inputLayout = render_->CreateInputLayout(entries); + inputLayoutMap_.Insert(key, inputLayout); + return inputLayout; } void DrawEngineGLES::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) { @@ -304,6 +362,17 @@ void DrawEngineGLES::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, i } } +void DrawEngineGLES::DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bindOffset, GLRBuffer **buf) { + u8 *dest = decoded; + + // Figure out how much pushbuffer space we need to allocate. + if (push) { + int vertsToDecode = ComputeNumVertsToDecode(); + dest = (u8 *)push->Push(vertsToDecode * dec_->GetDecVtxFmt().stride, bindOffset, buf); + } + DecodeVerts(dest); +} + void DrawEngineGLES::MarkUnreliable(VertexArrayInfo *vai) { vai->status = VertexArrayInfo::VAI_UNRELIABLE; if (vai->vbo) { @@ -430,18 +499,23 @@ void DrawEngineGLES::FreeVertexArray(VertexArrayInfo *vai) { void DrawEngineGLES::DoFlush() { PROFILE_THIS_SCOPE("flush"); - CHECK_GL_ERROR_IF_DEBUG(); + FrameData &frameData = frameData_[render_->GetCurFrame()]; + gpuStats.numFlushes++; gpuStats.numTrackedVertexArrays = (int)vai_.size(); GEPrimitiveType prim = prevPrim_; ApplyDrawState(prim); - CHECK_GL_ERROR_IF_DEBUG(); VShaderID vsid; Shader *vshader = shaderManager_->ApplyVertexShader(prim, lastVType_, &vsid); + GLRBuffer *vertexBuffer = nullptr; + GLRBuffer *indexBuffer = nullptr; + uint32_t vertexBufferOffset = 0; + uint32_t indexBufferOffset = 0; + if (vshader->UseHWTransform()) { GLuint vbo = 0, ebo = 0; int vertexCount = 0; @@ -453,6 +527,9 @@ void DrawEngineGLES::DoFlush() { if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) useCache = false; + // TEMPORARY + useCache = false; + if (useCache) { u32 id = dcid_ ^ gstate.getUVGenMode(); // This can have an effect on which UV decoder we need to use! And hence what the decoded data will look like. See #9263 VertexArrayInfo *vai = vai_.Get(id); @@ -597,7 +674,7 @@ void DrawEngineGLES::DoFlush() { vai->lastFrame = gpuStats.numFlips; } else { - DecodeVerts(decoded); + DecodeVertsToPushBuffer(frameData.pushVertex, &vertexBufferOffset, &vertexBuffer); rotateVBO: gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); @@ -606,9 +683,6 @@ rotateVBO: if (!useElements && indexGen.PureCount()) { vertexCount = indexGen.PureCount(); } - glstate.arrayBuffer.unbind(); - glstate.elementArrayBuffer.unbind(); - prim = indexGen.Prim(); } @@ -630,16 +704,21 @@ rotateVBO: } LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim); - SetupDecFmtForDraw(program, dec_->GetDecVtxFmt(), vbo ? 0 : decoded); - + GLRInputLayout *inputLayout = SetupDecFmtForDraw(program, dec_->GetDecVtxFmt()); + render_->BindVertexBuffer(vertexBuffer); + render_->BindInputLayout(inputLayout, (void *)(uintptr_t)vertexBufferOffset); if (useElements) { + if (!indexBuffer) { + indexBufferOffset = (uint32_t)frameData.pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), &indexBuffer); + render_->BindIndexBuffer(indexBuffer); + } if (gstate_c.bezier || gstate_c.spline) // Instanced rendering for instanced tessellation - glDrawElementsInstanced(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, ebo ? 0 : (GLvoid*)decIndex, numPatches); + ; // glDrawElementsInstanced(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset, numPatches); else - glDrawElements(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, ebo ? 0 : (GLvoid*)decIndex); + render_->DrawIndexed(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset); } else { - glDrawArrays(glprim[prim], 0, vertexCount); + render_->Draw(glprim[prim], 0, vertexCount); } } else { DecodeVerts(decoded); @@ -695,28 +774,18 @@ rotateVBO: bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX; - const uint8_t *bufferStart = (const uint8_t *)drawBuffer; - if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { - bufferStart = 0; - BindBuffer(drawBuffer, vertexSize * maxIndex); - if (drawIndexed) { - BindElementBuffer(inds, sizeof(short) * numTrans); - inds = 0; - } - } else { - glstate.arrayBuffer.unbind(); - glstate.elementArrayBuffer.unbind(); - } - - glVertexAttribPointer(ATTR_POSITION, 4, GL_FLOAT, GL_FALSE, vertexSize, bufferStart); - int attrMask = program->attrMask; - if (attrMask & (1 << ATTR_TEXCOORD)) glVertexAttribPointer(ATTR_TEXCOORD, doTextureProjection ? 3 : 2, GL_FLOAT, GL_FALSE, vertexSize, bufferStart + offsetof(TransformedVertex, u)); - if (attrMask & (1 << ATTR_COLOR0)) glVertexAttribPointer(ATTR_COLOR0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, bufferStart + offsetof(TransformedVertex, color0)); - if (attrMask & (1 << ATTR_COLOR1)) glVertexAttribPointer(ATTR_COLOR1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, bufferStart + offsetof(TransformedVertex, color1)); if (drawIndexed) { - glDrawElements(glprim[prim], numTrans, GL_UNSIGNED_SHORT, inds); + vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(drawBuffer, maxIndex * sizeof(TransformedVertex), &vertexBuffer); + indexBufferOffset = (uint32_t)frameData.pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), &indexBuffer); + render_->BindIndexBuffer(indexBuffer); + render_->BindVertexBuffer(vertexBuffer); + render_->BindInputLayout(softwareInputLayout_, (void *)(intptr_t)vertexBufferOffset); + render_->DrawIndexed(glprim[prim], numTrans, GL_UNSIGNED_SHORT, inds); } else { - glDrawArrays(glprim[prim], 0, numTrans); + vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(drawBuffer, numTrans * sizeof(TransformedVertex), &vertexBuffer); + render_->BindVertexBuffer(vertexBuffer); + render_->BindInputLayout(softwareInputLayout_, (void *)(intptr_t)vertexBufferOffset); + render_->Draw(glprim[prim], 0, numTrans); } } else if (result.action == SW_CLEAR) { u32 clearColor = result.color; @@ -735,26 +804,12 @@ rotateVBO: framebufferManager_->SetDepthUpdated(); } - // Note that scissor may still apply while clearing. Turn off other tests for the clear. - glstate.stencilTest.disable(); - glstate.stencilMask.set(0xFF); - glstate.depthTest.disable(); - GLbitfield target = 0; if (colorMask || alphaMask) target |= GL_COLOR_BUFFER_BIT; if (alphaMask) target |= GL_STENCIL_BUFFER_BIT; if (depthMask) target |= GL_DEPTH_BUFFER_BIT; - glstate.colorMask.set(colorMask, colorMask, colorMask, alphaMask); - glClearColor(col[0], col[1], col[2], col[3]); -#ifdef USING_GLES2 - glClearDepthf(clearDepth); -#else - glClearDepth(clearDepth); -#endif - // Stencil takes alpha. - glClearStencil(clearColor >> 24); - glClear(target); + render_->Clear(clearColor, clearDepth, clearColor >> 24, target); framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); int scissorX1 = gstate.getScissorX1(); @@ -766,6 +821,7 @@ rotateVBO: if (g_Config.bBlockTransferGPU && (gstate_c.featureFlags & GPU_USE_CLEAR_RAM_HACK) && colorMask && (alphaMask || gstate.FrameBufFormat() == GE_FORMAT_565)) { framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor); } + gstate_c.Dirty(DIRTY_BLEND_STATE); // Make sure the color mask gets re-applied. } } diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index f50b0ffb35..ce2b51d025 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -28,6 +28,7 @@ #include "GPU/Common/GPUStateUtils.h" #include "GPU/GLES/FragmentShaderGeneratorGLES.h" #include "gfx/gl_common.h" +#include "thin3d/GLRenderManager.h" class LinkedShader; class ShaderManagerGLES; @@ -126,6 +127,10 @@ public: void ClearTrackedVertexArrays() override; void DecimateTrackedVertexArrays(); + void BeginFrame(); + void EndFrame(); + + // So that this can be inlined void Flush() { if (!numDrawCalls) @@ -151,6 +156,8 @@ public: GLuint BindElementBuffer(const void *p, size_t sz); void DecimateBuffers(); + void ClearInputLayoutMap(); + private: void InitDeviceObjects(); void DestroyDeviceObjects(); @@ -160,14 +167,28 @@ private: void ApplyDrawStateLate(); void ResetShaderBlending(); + GLRInputLayout *SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt); + + void DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bindOffset, GLRBuffer **buf); + GLuint AllocateBuffer(size_t sz); void FreeBuffer(GLuint buf); void FreeVertexArray(VertexArrayInfo *vai); void MarkUnreliable(VertexArrayInfo *vai); + struct FrameData { + GLPushBuffer *pushVertex; + GLPushBuffer *pushIndex; + }; + FrameData frameData_[GLRenderManager::MAX_INFLIGHT_FRAMES]; + PrehashMap vai_; + DenseHashMap inputLayoutMap_; + + GLRInputLayout *softwareInputLayout_ = nullptr; + // Vertex buffer objects // Element buffer objects struct BufferNameInfo { @@ -177,6 +198,7 @@ private: bool used; int lastFrame; }; + GLRenderManager *render_; std::vector bufferNameCache_; std::multimap freeSizedBuffers_; std::unordered_map bufferNameInfo_; diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 20eb4aaf8c..bcda525e8a 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -82,6 +82,7 @@ const int MAX_PBO = 2; void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format); void FramebufferManagerGLES::DisableState() { + /* glstate.blend.disable(); glstate.cullFace.disable(); glstate.depthTest.disable(); @@ -92,7 +93,7 @@ void FramebufferManagerGLES::DisableState() { #endif glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glstate.stencilMask.set(0xFF); - + */ gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); } @@ -247,6 +248,7 @@ FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) : needBackBufferYSwap_ = true; needGLESRebinds_ = true; CreateDeviceObjects(); + render_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); } void FramebufferManagerGLES::Init() { diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 94c87ae982..d7686a0c96 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -29,6 +29,7 @@ #include "Core/Config.h" #include "GPU/GPUCommon.h" #include "GPU/Common/FramebufferCommon.h" +#include "thin3d/GLRenderManager.h" struct GLSLProgram; class TextureCacheGLES; @@ -110,6 +111,8 @@ private: void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h) override; void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); + GLRenderManager *render_; + // Used by DrawPixels unsigned int drawPixelsTex_; GEBufferFormat drawPixelsTexFormat_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 78528e7a19..beb5fbbfc4 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -403,6 +403,10 @@ void GPU_GLES::BuildReportingInfo() { void GPU_GLES::DeviceLost() { ILOG("GPU_GLES: DeviceLost"); + // Simply drop all caches and textures. + // FBOs appear to survive? Or no? + // TransformDraw has registered as a GfxResourceHolder. + drawEngine_.ClearInputLayoutMap(); shaderManagerGL_->ClearCache(false); textureCacheGL_->Clear(false); fragmentTestCache_.Clear(false); @@ -451,6 +455,12 @@ void GPU_GLES::BeginHostFrame() { shaderManagerGL_->DirtyShader(); textureCacheGL_->NotifyConfigChanged(); } + + drawEngine_.BeginFrame(); +} + +void GPU_GLES::EndHostFrame() { + drawEngine_.EndFrame(); } inline void GPU_GLES::UpdateVsyncInterval(bool force) { diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index f99fe6d3e3..4378f166a7 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -80,6 +80,7 @@ public: std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; void BeginHostFrame() override; + void EndHostFrame() override; protected: void FastRunLoop(DisplayList &list) override; diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index b2a54a3d42..08b9072feb 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -166,21 +166,15 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, attrMask = vs->GetAttrMask(); availableUniforms = vs->GetUniformMask() | fs->GetUniformMask(); - program = render->CreateProgram(shaders, semantics, queries, gstate_c.featureFlags & GPU_SUPPORTS_DUALSOURCE_BLEND); + std::vector initialize; + initialize.push_back({ &u_tex, 0, 0 }); + initialize.push_back({ &u_fbotex, 0, 1 }); + initialize.push_back({ &u_testtex, 0, 2 }); + initialize.push_back({ &u_tess_pos_tex, 4 }); // Texture unit 4 + initialize.push_back({ &u_tess_tex_tex, 5 }); // Texture unit 5 + initialize.push_back({ &u_tess_col_tex, 6 }); // Texture unit 6 - render->BindProgram(program); - - // Default uniform values - render->SetUniformI1(&u_tex, 0); - render->SetUniformI1(&u_fbotex, 1); - render->SetUniformI1(&u_fbotex, 2); - - if (u_tess_pos_tex != -1) - render->SetUniformI1(&u_tess_pos_tex, 4); // Texture unit 4 - if (u_tess_tex_tex != -1) - render->SetUniformI1(&u_tess_tex_tex, 5); // Texture unit 5 - if (u_tess_col_tex != -1) - render->SetUniformI1(&u_tess_col_tex, 6); // Texture unit 6 + program = render->CreateProgram(shaders, semantics, queries, initialize, gstate_c.featureFlags & GPU_SUPPORTS_DUALSOURCE_BLEND); // The rest, use the "dirty" mechanism. dirtyUniforms = DIRTY_ALL_UNIFORMS; diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index f810087770..54acebcb1c 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -230,10 +230,14 @@ void DrawEngineGLES::ApplyDrawState(int prim) { } #endif int mask = (int)rmask | ((int)gmask << 1) | ((int)bmask << 2) | ((int)amask << 3); - renderManager->SetBlendAndMask(mask, blendState.enabled, - glBlendFactorLookup[(size_t)blendState.srcColor], glBlendFactorLookup[(size_t)blendState.dstColor], - glBlendFactorLookup[(size_t)blendState.srcAlpha], glBlendFactorLookup[(size_t)blendState.dstAlpha], - glBlendEqLookup[(size_t)blendState.eqColor], glBlendEqLookup[(size_t)blendState.eqAlpha]); + if (blendState.enabled) { + renderManager->SetBlendAndMask(mask, blendState.enabled, + glBlendFactorLookup[(size_t)blendState.srcColor], glBlendFactorLookup[(size_t)blendState.dstColor], + glBlendFactorLookup[(size_t)blendState.srcAlpha], glBlendFactorLookup[(size_t)blendState.dstAlpha], + glBlendEqLookup[(size_t)blendState.eqColor], glBlendEqLookup[(size_t)blendState.eqAlpha]); + } else { + renderManager->SetNoBlendAndMask(mask); + } #ifndef USING_GLES2 if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { @@ -288,9 +292,13 @@ void DrawEngineGLES::ApplyDrawState(int prim) { GenericStencilFuncState stencilState; ConvertStencilFuncState(stencilState); // Stencil Test - renderManager->SetStencil(stencilState.enabled, compareOps[stencilState.testFunc], - stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass], - stencilState.writeMask, stencilState.testMask, stencilState.testRef); + if (stencilState.enabled) { + renderManager->SetStencil(stencilState.enabled, compareOps[stencilState.testFunc], + stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass], + stencilState.writeMask, stencilState.testMask, stencilState.testRef); + } else { + renderManager->SetStencilDisabled(); + } } } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index c186ea065d..0ddc148c0d 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -70,7 +70,6 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { } } #endif - glLinkProgram(program->program); GLint linkStatus = GL_FALSE; @@ -111,8 +110,17 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { *x.dest = glGetUniformLocation(program->program, x.name); } - // Here we could (using glGetAttribLocation) save a bitmask about which pieces of vertex data are used in the shader - // and then AND it with the vertex format bitmask later... + // Run initializers. + for (int i = 0; i < program->initialize_.size(); i++) { + auto &init = program->initialize_[i]; + GLint uniform = *init.uniform; + if (uniform != -1) { + switch (init.type) { + case 0: + glUniform1i(uniform, init.value); + } + } + } } break; case GLRInitStepType::CREATE_SHADER: @@ -240,8 +248,11 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } else { glDisable(GL_BLEND); } + glColorMask(c.blend.mask & 1, (c.blend.mask >> 1) & 1, (c.blend.mask >> 2) & 1, (c.blend.mask >> 3) & 1); break; case GLRRenderCommand::CLEAR: + glDisable(GL_SCISSOR_TEST); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); if (c.clear.clearMask & GL_COLOR_BUFFER_BIT) { float color[4]; Uint8x4ToFloat4(color, c.clear.clearColor); @@ -258,6 +269,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glClearStencil(c.clear.clearStencil); } glClear(c.clear.clearMask); + glEnable(GL_SCISSOR_TEST); break; case GLRRenderCommand::BLENDCOLOR: glBlendColor(c.blendColor.color[0], c.blendColor.color[1], c.blendColor.color[2], c.blendColor.color[3]); @@ -376,6 +388,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glBindBuffer(GL_ARRAY_BUFFER, buf); break; } + case GLRRenderCommand::BIND_INDEX_BUFFER: + { + GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); + break; + } case GLRRenderCommand::GENMIPS: glGenerateMipmap(GL_TEXTURE_2D); break; diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index f3d5c7df17..810027d461 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -44,6 +44,7 @@ enum class GLRRenderCommand : uint8_t { BIND_FB_TEXTURE, BIND_INPUT_LAYOUT, BIND_VERTEX_BUFFER, + BIND_INDEX_BUFFER, GENMIPS, DRAW, DRAW_INDEXED, diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 226aed1458..1c05cc4577 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -352,6 +352,14 @@ GLPushBuffer::~GLPushBuffer() { assert(buffers_.empty()); } +void GLPushBuffer::Map() { + assert(!writePtr_); + // TODO: Even a good old glMapBuffer could actually work well here. + // VkResult res = vkMapMemory(device_, buffers_[buf_].deviceMemory, 0, size_, 0, (void **)(&writePtr_)); + writePtr_ = buffers_[buf_].deviceMemory; + assert(writePtr_); +} + void GLPushBuffer::Unmap() { assert(writePtr_); // Here we should simply upload everything to the buffers. diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index cd77d12152..a3ee244b9f 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -89,9 +89,16 @@ public: const char *name; }; + struct Initializer { + GLint *uniform; + int type; + int value; + }; + GLuint program = 0; std::vector semantics_; std::vector queries_; + std::vector initialize_; struct UniformInfo { int loc_; @@ -222,12 +229,15 @@ public: return step.create_shader.shader; } - GLRProgram *CreateProgram(std::vector shaders, std::vector semantics, std::vector queries, bool supportDualSource) { + GLRProgram *CreateProgram( + std::vector shaders, std::vector semantics, std::vector queries, + std::vector initalizers, bool supportDualSource) { GLRInitStep step{ GLRInitStepType::CREATE_PROGRAM }; assert(shaders.size() <= ARRAY_SIZE(step.create_program.shaders)); step.create_program.program = new GLRProgram(); step.create_program.program->semantics_ = semantics; step.create_program.program->queries_ = queries; + step.create_program.program->initialize_ = initalizers; for (int i = 0; i < shaders.size(); i++) { step.create_program.shaders[i] = shaders[i]; } @@ -327,6 +337,13 @@ public: curRenderStep_->commands.push_back(data); } + void BindIndexBuffer(GLRBuffer *buffer) { // Want to support an offset but can't in ES 2.0. We supply an offset when binding the buffers instead. + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::BIND_INDEX_BUFFER}; + data.bind_buffer.buffer = buffer; + curRenderStep_->commands.push_back(data); + } + void BindInputLayout(GLRInputLayout *inputLayout, const void *offset) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); assert(inputLayout); @@ -403,7 +420,7 @@ public: void SetUniformM4x4(GLint *loc, const float *udata) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; + GLRRenderData data{ GLRRenderCommand::UNIFORMMATRIX }; data.uniformMatrix4.loc = loc; memcpy(data.uniformMatrix4.m, udata, sizeof(float) * 16); curRenderStep_->commands.push_back(data); @@ -442,6 +459,7 @@ public: void SetStencil(bool enabled, GLenum func, GLenum sFail, GLenum zFail, GLenum pass, uint8_t writeMask, uint8_t compareMask, uint8_t refValue) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::STENCIL }; + data.stencil.enabled = enabled; data.stencil.func = func; data.stencil.sFail = sFail; data.stencil.zFail = zFail; @@ -452,6 +470,14 @@ public: curRenderStep_->commands.push_back(data); } + void SetStencilDisabled() { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data; + data.cmd = GLRRenderCommand::STENCIL; + data.stencil.enabled = false; + curRenderStep_->commands.push_back(data); + } + void SetBlendFactor(const float color[4]) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::BLENDCOLOR }; @@ -613,13 +639,7 @@ public: Unmap(); } - void Map() { - assert(!writePtr_); - // VkResult res = vkMapMemory(device_, buffers_[buf_].deviceMemory, 0, size_, 0, (void **)(&writePtr_)); - writePtr_ = buffers_[buf_].deviceMemory; - assert(writePtr_); - } - + void Map(); void Unmap(); // When using the returned memory, make sure to bind the returned vkbuf. diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 6ba2d06b38..1331a34f2d 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -1099,7 +1099,8 @@ bool OpenGLPipeline::LinkShaders() { semantics.push_back({ SEM_TANGENT, "Tangent" }); semantics.push_back({ SEM_BINORMAL, "Binormal" }); std::vector queries; - program_ = render_->CreateProgram(linkShaders, semantics, queries, false); + std::vector initialize; + program_ = render_->CreateProgram(linkShaders, semantics, queries, initialize, false); return true; } From bd6818198ad49e42f82a1fdc711289ec51592c82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 19 Nov 2017 17:37:56 +0100 Subject: [PATCH 010/291] More GLRenderManager --- GPU/Common/TextureCacheCommon.cpp | 2 +- GPU/Common/TextureCacheCommon.h | 4 +- GPU/GLES/DepalettizeShaderGLES.cpp | 116 ++++++++------------------ GPU/GLES/DepalettizeShaderGLES.h | 17 ++-- GPU/GLES/DrawEngineGLES.h | 2 +- GPU/GLES/FragmentTestCacheGLES.cpp | 38 +++------ GPU/GLES/FragmentTestCacheGLES.h | 13 +-- GPU/GLES/FramebufferManagerGLES.cpp | 16 ++-- GPU/GLES/FramebufferManagerGLES.h | 2 +- GPU/GLES/GPU_GLES.cpp | 2 +- GPU/GLES/TextureCacheGLES.cpp | 67 +++++---------- GPU/GLES/TextureCacheGLES.h | 13 ++- Windows/GPU/WindowsGLContext.cpp | 2 +- ext/native/thin3d/GLQueueRunner.cpp | 52 ++++++++++-- ext/native/thin3d/GLQueueRunner.h | 17 +++- ext/native/thin3d/GLRenderManager.cpp | 11 +++ ext/native/thin3d/GLRenderManager.h | 41 ++++----- ext/native/thin3d/thin3d_gl.cpp | 30 ++++--- 18 files changed, 210 insertions(+), 235 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 1485a333a3..bcfa89ed31 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -383,7 +383,7 @@ void TextureCacheCommon::SetTexture(bool force) { // Exponential backoff up to 512 frames. Textures are often reused. if (entry->numFrames > 32) { // Also, try to add some "randomness" to avoid rehashing several textures the same frame. - entry->framesUntilNextFullHash = std::min(512, entry->numFrames) + (entry->textureName & 15); + entry->framesUntilNextFullHash = std::min(512, entry->numFrames) + (((intptr_t)entry->textureName >> 8) & 15); } else { entry->framesUntilNextFullHash = entry->numFrames; } diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 31aa6eeb97..aa69f123a5 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -87,6 +87,8 @@ struct SamplerCacheKey { } }; +class GLRTexture; + // TODO: Shrink this struct. There is some fluff. struct TexCacheEntry { ~TexCacheEntry() { @@ -132,7 +134,7 @@ struct TexCacheEntry { u16 dim; u16 bufw; union { - u32 textureName; + GLRTexture *textureName; void *texturePtr; CachedTextureVulkan *vkTex; }; diff --git a/GPU/GLES/DepalettizeShaderGLES.cpp b/GPU/GLES/DepalettizeShaderGLES.cpp index 71ef33d4c2..7e56ce8525 100644 --- a/GPU/GLES/DepalettizeShaderGLES.cpp +++ b/GPU/GLES/DepalettizeShaderGLES.cpp @@ -89,7 +89,8 @@ static bool CheckShaderCompileSuccess(GLuint shader, const char *code) { } } -DepalShaderCacheGLES::DepalShaderCacheGLES() { +DepalShaderCacheGLES::DepalShaderCacheGLES(Draw::DrawContext *draw) { + render_ = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); // Pre-build the vertex program useGL3_ = gl_extensions.GLES3 || gl_extensions.VersionGEThan(3, 3); @@ -102,25 +103,12 @@ DepalShaderCacheGLES::~DepalShaderCacheGLES() { } bool DepalShaderCacheGLES::CreateVertexShader() { - if (vertexShaderFailed_) { - return false; - } - - vertexShader_ = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertexShader_, 1, useGL3_ ? &depalVShader300 : &depalVShader100, 0); - glCompileShader(vertexShader_); - - if (!CheckShaderCompileSuccess(vertexShader_, useGL3_ ? depalVShader300 : depalVShader100)) { - glDeleteShader(vertexShader_); - vertexShader_ = 0; - // Don't try to recompile. - vertexShaderFailed_ = true; - } - - return !vertexShaderFailed_; + std::string src(useGL3_ ? depalVShader300 : depalVShader100); + vertexShader_ = render_->CreateShader(GL_VERTEX_SHADER, src); + return true; } -GLuint DepalShaderCacheGLES::GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, u32 *rawClut) { +GLRTexture *DepalShaderCacheGLES::GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, u32 *rawClut) { u32 clutId = GetClutID(clutFormat, clutHash); auto oldtex = texCache_.find(clutId); @@ -133,18 +121,11 @@ GLuint DepalShaderCacheGLES::GetClutTexture(GEPaletteFormat clutFormat, const u3 int texturePixels = clutFormat == GE_CMODE_32BIT_ABGR8888 ? 256 : 512; DepalTexture *tex = new DepalTexture(); - glGenTextures(1, &tex->texture); - glBindTexture(GL_TEXTURE_2D, tex->texture); + tex->texture = render_->CreateTexture(GL_TEXTURE_2D); GLuint components = dstFmt == GL_UNSIGNED_SHORT_5_6_5 ? GL_RGB : GL_RGBA; - GLuint components2 = components; - glTexImage2D(GL_TEXTURE_2D, 0, components, texturePixels, 1, 0, components2, dstFmt, (void *)rawClut); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + render_->TextureImage(tex->texture, 0, texturePixels, 1, components, components2, dstFmt, (uint8_t *)rawClut, false); tex->lastFrame = gpuStats.numFlips; texCache_[clutId] = tex; @@ -153,20 +134,20 @@ GLuint DepalShaderCacheGLES::GetClutTexture(GEPaletteFormat clutFormat, const u3 void DepalShaderCacheGLES::Clear() { for (auto shader = cache_.begin(); shader != cache_.end(); ++shader) { - glDeleteShader(shader->second->fragShader); + render_->DeleteShader(shader->second->fragShader); if (shader->second->program) { - glDeleteProgram(shader->second->program); + render_->DeleteProgram(shader->second->program); } delete shader->second; } cache_.clear(); for (auto tex = texCache_.begin(); tex != texCache_.end(); ++tex) { - glDeleteTextures(1, &tex->second->texture); + render_->DeleteTexture(tex->second->texture); delete tex->second; } texCache_.clear(); if (vertexShader_) { - glDeleteShader(vertexShader_); + render_->DeleteShader(vertexShader_); vertexShader_ = 0; } } @@ -174,7 +155,7 @@ void DepalShaderCacheGLES::Clear() { void DepalShaderCacheGLES::Decimate() { for (auto tex = texCache_.begin(); tex != texCache_.end(); ) { if (tex->second->lastFrame + DEPAL_TEXTURE_OLD_AGE < gpuStats.numFlips) { - glDeleteTextures(1, &tex->second->texture); + render_->DeleteTexture(tex->second->texture); delete tex->second; texCache_.erase(tex++); } else { @@ -201,64 +182,35 @@ DepalShader *DepalShaderCacheGLES::GetDepalettizeShader(uint32_t clutMode, GEBuf char *buffer = new char[2048]; GenerateDepalShader(buffer, pixelFormat, useGL3_ ? GLSL_300 : GLSL_140); - - GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *buf = buffer; - glShaderSource(fragShader, 1, &buf, 0); - glCompileShader(fragShader); - - CheckShaderCompileSuccess(fragShader, buffer); - - GLuint program = glCreateProgram(); - glAttachShader(program, vertexShader_); - glAttachShader(program, fragShader); - glBindAttribLocation(program, 0, "a_position"); - glBindAttribLocation(program, 1, "a_texcoord0"); - - glLinkProgram(program); - glUseProgram(program); - - GLint u_tex = glGetUniformLocation(program, "tex"); - GLint u_pal = glGetUniformLocation(program, "pal"); - - glUniform1i(u_tex, 0); - glUniform1i(u_pal, 3); + std::string src(buffer); + GLRShader *fragShader = render_->CreateShader(GL_FRAGMENT_SHADER, src); DepalShader *depal = new DepalShader(); + + std::vector semantics; + semantics.push_back({ 0, "a_position" }); + semantics.push_back({ 1, "a_texcoord0" }); + + std::vector queries; + queries.push_back({ &depal->u_tex, "tex" }); + queries.push_back({ &depal->u_pal, "pal" }); + + std::vector initializer; + initializer.push_back({ &depal->u_tex, 0 }); + initializer.push_back({ &depal->u_pal, 3 }); + + std::vector shaders{ vertexShader_, fragShader }; + + GLRProgram *program = render_->CreateProgram(shaders, semantics, queries, initializer, false); + depal->program = program; depal->fragShader = fragShader; depal->code = buffer; + depal->a_position = 0; + depal->a_texcoord0 = 1; cache_[id] = depal; - GLint linkStatus = GL_FALSE; - glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) { - GLint bufLength = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); - if (bufLength) { - char* errorbuf = new char[bufLength]; - glGetProgramInfoLog(program, bufLength, NULL, errorbuf); -#ifdef SHADERLOG - OutputDebugStringUTF8(buffer); - OutputDebugStringUTF8(errorbuf); -#endif - ERROR_LOG(G3D, "Could not link program:\n %s \n\n %s", errorbuf, buf); - delete[] errorbuf; // we're dead! - } - - // Since it failed, let's mark it in the cache so we don't keep retrying. - // That will only make it slower. - depal->program = 0; - - // We will delete the shader later in Clear(). - glDeleteProgram(program); - } else { - depal->a_position = glGetAttribLocation(program, "a_position"); - depal->a_texcoord0 = glGetAttribLocation(program, "a_texcoord0"); - } - delete[] buffer; return depal->program ? depal : nullptr; } diff --git a/GPU/GLES/DepalettizeShaderGLES.h b/GPU/GLES/DepalettizeShaderGLES.h index a32acb2cb3..bc3e93facd 100644 --- a/GPU/GLES/DepalettizeShaderGLES.h +++ b/GPU/GLES/DepalettizeShaderGLES.h @@ -19,34 +19,38 @@ #include "Common/CommonTypes.h" #include "gfx/gl_common.h" +#include "thin3d/thin3d.h" +#include "thin3d/GLRenderManager.h" #include "GPU/ge_constants.h" #include "GPU/Common/ShaderCommon.h" #include "GPU/Common/DepalettizeShaderCommon.h" class DepalShader { public: - GLuint program; - GLuint fragShader; + GLRProgram *program; + GLRShader *fragShader; GLint a_position; GLint a_texcoord0; + GLint u_tex; + GLint u_pal; std::string code; }; class DepalTexture { public: - GLuint texture; + GLRTexture *texture; int lastFrame; }; // Caches both shaders and palette textures. class DepalShaderCacheGLES : public DepalShaderCacheCommon { public: - DepalShaderCacheGLES(); + DepalShaderCacheGLES(Draw::DrawContext *draw); ~DepalShaderCacheGLES(); // This also uploads the palette and binds the correct texture. DepalShader *GetDepalettizeShader(uint32_t clutMode, GEBufferFormat pixelFormat); - GLuint GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, u32 *rawClut); + GLRTexture *GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, u32 *rawClut); void Clear(); void Decimate(); std::vector DebugGetShaderIDs(DebugShaderType type); @@ -55,9 +59,10 @@ public: private: bool CreateVertexShader(); + GLRenderManager *render_; bool useGL3_; bool vertexShaderFailed_; - GLuint vertexShader_; + GLRShader *vertexShader_; std::map cache_; std::map texCache_; }; diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index ce2b51d025..2ed6046b96 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -141,7 +141,7 @@ public: void FinishDeferred() { if (!numDrawCalls) return; - DecodeVerts(decoded); + DoFlush(); } bool IsCodePtrVertexDecoder(const u8 *ptr) const; diff --git a/GPU/GLES/FragmentTestCacheGLES.cpp b/GPU/GLES/FragmentTestCacheGLES.cpp index e49f336e13..0228f3896e 100644 --- a/GPU/GLES/FragmentTestCacheGLES.cpp +++ b/GPU/GLES/FragmentTestCacheGLES.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "thin3d/thin3d.h" #include "gfx/gl_debug_log.h" #include "Core/Config.h" #include "GPU/GLES/FragmentTestCacheGLES.h" @@ -26,7 +27,8 @@ static const int FRAGTEST_TEXTURE_OLD_AGE = 307; static const int FRAGTEST_DECIMATION_INTERVAL = 113; -FragmentTestCacheGLES::FragmentTestCacheGLES() : textureCache_(NULL), lastTexture_(0), decimationCounter_(0) { +FragmentTestCacheGLES::FragmentTestCacheGLES(Draw::DrawContext *draw) { + render_ = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); scratchpad_ = new u8[256 * 4]; } @@ -51,17 +53,12 @@ void FragmentTestCacheGLES::BindTestTexture(GLenum unit) { const auto cached = cache_.find(id); if (cached != cache_.end()) { cached->second.lastFrame = gpuStats.numFlips; - GLuint tex = cached->second.texture; + GLRTexture *tex = cached->second.texture; if (tex == lastTexture_) { // Already bound, hurray. return; } - CHECK_GL_ERROR_IF_DEBUG(); - glActiveTexture(unit); - glBindTexture(GL_TEXTURE_2D, tex); - // Always return to the default. - glActiveTexture(GL_TEXTURE0); - CHECK_GL_ERROR_IF_DEBUG(); + render_->BindTexture(unit, tex); lastTexture_ = tex; return; } @@ -79,13 +76,9 @@ void FragmentTestCacheGLES::BindTestTexture(GLenum unit) { const GEComparison funcs[4] = {gstate.getColorTestFunction(), gstate.getColorTestFunction(), gstate.getColorTestFunction(), gstate.getAlphaTestFunction()}; const bool valid[4] = {gstate.isColorTestEnabled(), gstate.isColorTestEnabled(), gstate.isColorTestEnabled(), gstate.isAlphaTestEnabled()}; - glActiveTexture(unit); - // This will necessarily bind the texture. - const GLuint tex = CreateTestTexture(funcs, refs, masks, valid); - // Always return to the default. - glActiveTexture(GL_TEXTURE0); + GLRTexture *tex = CreateTestTexture(funcs, refs, masks, valid); lastTexture_ = tex; - + render_->BindTexture(unit, tex); FragmentTestTexture item; item.lastFrame = gpuStats.numFlips; item.texture = tex; @@ -106,7 +99,7 @@ FragmentTestID FragmentTestCacheGLES::GenerateTestID() const { return id; } -GLuint FragmentTestCacheGLES::CreateTestTexture(const GEComparison funcs[4], const u8 refs[4], const u8 masks[4], const bool valid[4]) { +GLRTexture *FragmentTestCacheGLES::CreateTestTexture(const GEComparison funcs[4], const u8 refs[4], const u8 masks[4], const bool valid[4]) { // TODO: Might it be better to use GL_ALPHA for simple textures? // TODO: Experiment with 4-bit/etc. textures. @@ -146,22 +139,15 @@ GLuint FragmentTestCacheGLES::CreateTestTexture(const GEComparison funcs[4], con } } - GLuint tex = textureCache_->AllocTextureName(); - glBindTexture(GL_TEXTURE_2D, tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, scratchpad_); - - 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_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - + GLRTexture *tex = render_->CreateTexture(GL_TEXTURE_2D); + render_->TextureImage(tex, 0, 256, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, scratchpad_); return tex; } void FragmentTestCacheGLES::Clear(bool deleteThem) { if (deleteThem) { for (auto tex = cache_.begin(); tex != cache_.end(); ++tex) { - glDeleteTextures(1, &tex->second.texture); + render_->DeleteTexture(tex->second.texture); } } cache_.clear(); @@ -172,7 +158,7 @@ void FragmentTestCacheGLES::Decimate() { if (--decimationCounter_ <= 0) { for (auto tex = cache_.begin(); tex != cache_.end(); ) { if (tex->second.lastFrame + FRAGTEST_TEXTURE_OLD_AGE < gpuStats.numFlips) { - glDeleteTextures(1, &tex->second.texture); + render_->DeleteTexture(tex->second.texture); cache_.erase(tex++); } else { ++tex; diff --git a/GPU/GLES/FragmentTestCacheGLES.h b/GPU/GLES/FragmentTestCacheGLES.h index 106258e6d0..95eecb23cb 100644 --- a/GPU/GLES/FragmentTestCacheGLES.h +++ b/GPU/GLES/FragmentTestCacheGLES.h @@ -53,13 +53,13 @@ struct FragmentTestID { }; struct FragmentTestTexture { - GLuint texture; + GLRTexture *texture; int lastFrame; }; class FragmentTestCacheGLES { public: - FragmentTestCacheGLES(); + FragmentTestCacheGLES(Draw::DrawContext *draw); ~FragmentTestCacheGLES(); void SetTextureCache(TextureCacheGLES *tc) { @@ -73,13 +73,14 @@ public: private: - GLuint CreateTestTexture(const GEComparison funcs[4], const u8 refs[4], const u8 masks[4], const bool valid[4]); + GLRTexture *CreateTestTexture(const GEComparison funcs[4], const u8 refs[4], const u8 masks[4], const bool valid[4]); FragmentTestID GenerateTestID() const; + GLRenderManager *render_; TextureCacheGLES *textureCache_; std::map cache_; - u8 *scratchpad_; - GLuint lastTexture_; - int decimationCounter_; + u8 *scratchpad_ = nullptr; + GLRTexture *lastTexture_ = nullptr; + int decimationCounter_ = 0; }; diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index bcda525e8a..fccf90b1f3 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -287,9 +287,9 @@ void FramebufferManagerGLES::DestroyDeviceObjects() { postShaderProgram_ = nullptr; } if (drawPixelsTex_) { - glDeleteTextures(1, &drawPixelsTex_); - drawPixelsTex_ = 0; - } + render_->DeleteTexture(drawPixelsTex_); + drawPixelsTex_ = 0; + } if (stencilUploadProgram_) { glsl_destroy(stencilUploadProgram_); stencilUploadProgram_ = nullptr; @@ -320,15 +320,16 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma } if (drawPixelsTex_ && (drawPixelsTexFormat_ != srcPixelFormat || drawPixelsTexW_ != texWidth || drawPixelsTexH_ != height)) { - glDeleteTextures(1, &drawPixelsTex_); - drawPixelsTex_ = 0; + render_->DeleteTexture(drawPixelsTex_); + drawPixelsTex_ = nullptr; } if (!drawPixelsTex_) { - drawPixelsTex_ = textureCacheGL_->AllocTextureName(); + drawPixelsTex_ = render_->CreateTexture(GL_TEXTURE_2D); drawPixelsTexW_ = texWidth; drawPixelsTexH_ = height; + /* // Initialize backbuffer texture for DrawPixels glBindTexture(GL_TEXTURE_2D, drawPixelsTex_); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -338,9 +339,10 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + */ drawPixelsTexFormat_ = srcPixelFormat; } else { - glBindTexture(GL_TEXTURE_2D, drawPixelsTex_); + render_->BindTexture(0, drawPixelsTex_); } // TODO: We can just change the texture format and flip some bits around instead of this. diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index d7686a0c96..42d675ebe9 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -114,7 +114,7 @@ private: GLRenderManager *render_; // Used by DrawPixels - unsigned int drawPixelsTex_; + GLRTexture *drawPixelsTex_; GEBufferFormat drawPixelsTexFormat_; int drawPixelsTexW_; int drawPixelsTexH_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index beb5fbbfc4..594c980f05 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -79,7 +79,7 @@ static const GLESCommandTableEntry commandTable[] = { GPU_GLES::CommandInfo GPU_GLES::cmdInfo_[256]; GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) -: GPUCommon(gfxCtx, draw), drawEngine_(draw) { +: GPUCommon(gfxCtx, draw), drawEngine_(draw), fragmentTestCache_(draw), depalShaderCache_(draw) { UpdateVsyncInterval(true); CheckGPUFeatures(); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 430d4368b3..b841a32f23 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -23,6 +23,7 @@ #include "i18n/i18n.h" #include "math/math_util.h" #include "profiler/profiler.h" +#include "thin3d/GLRenderManager.h" #include "Common/ColorConv.h" #include "Core/Config.h" @@ -48,14 +49,12 @@ #define GL_UNPACK_ROW_LENGTH 0x0CF2 #endif -#define TEXCACHE_NAME_CACHE_SIZE 16 - TextureCacheGLES::TextureCacheGLES(Draw::DrawContext *draw) : TextureCacheCommon(draw) { timesInvalidatedAllThisFrame_ = 0; - lastBoundTexture = INVALID_TEX; + lastBoundTexture = nullptr; + render_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel); SetupTextureDecoder(); nextTexture_ = nullptr; @@ -73,21 +72,15 @@ void TextureCacheGLES::SetFramebufferManager(FramebufferManagerGLES *fbManager) void TextureCacheGLES::ReleaseTexture(TexCacheEntry *entry, bool delete_them) { DEBUG_LOG(G3D, "Deleting texture %i", entry->textureName); if (delete_them) { - if (entry->textureName != 0) { - glDeleteTextures(1, &entry->textureName); + if (entry->textureName) { + render_->DeleteTexture(entry->textureName); } } - entry->textureName = 0; + entry->textureName = nullptr; } void TextureCacheGLES::Clear(bool delete_them) { TextureCacheCommon::Clear(delete_them); - if (delete_them) { - if (!nameCache_.empty()) { - glDeleteTextures((GLsizei)nameCache_.size(), &nameCache_[0]); - nameCache_.clear(); - } - } } GLenum getClutDestFormat(GEPaletteFormat format) { @@ -165,10 +158,8 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { } if (force || entry.minFilt != minFilt || entry.magFilt != magFilt || entry.sClamp != sClamp || entry.tClamp != tClamp) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFiltGL[minFilt]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFiltGL[magFilt]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + float aniso = 0.0f; + render_->SetTextureSampler(sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); entry.minFilt = minFilt; entry.magFilt = magFilt; entry.sClamp = sClamp; @@ -188,10 +179,8 @@ void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferH minFilt &= 1; // framebuffers can't mipmap. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFiltGL[minFilt]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFiltGL[magFilt]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + float aniso = 0.0f; + render_->SetTextureSampler(sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); // Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case. // This happens whether we have OES_texture_npot or not. @@ -325,14 +314,14 @@ bool SetDebugTexture() { void TextureCacheGLES::BindTexture(TexCacheEntry *entry) { if (entry->textureName != lastBoundTexture) { - glBindTexture(GL_TEXTURE_2D, entry->textureName); + render_->BindTexture(0, entry->textureName); lastBoundTexture = entry->textureName; } UpdateSamplingParams(*entry, false); } void TextureCacheGLES::Unbind() { - glBindTexture(GL_TEXTURE_2D, 0); + render_->BindTexture(0, nullptr); InvalidateLastTexture(); } @@ -413,8 +402,8 @@ public: } } - void Use(DrawEngineGLES *transformDraw) { - glUseProgram(shader_->program); + void Use(GLRenderManager *render, DrawEngineGLES *transformDraw) { + render->BindProgram(shader_->program); // Restore will rebind all of the state below. if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { @@ -476,18 +465,16 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram } if (depal) { const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat(); - GLuint clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_); + GLRTexture *clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_); Draw::Framebuffer *depalFBO = framebufferManagerGL_->GetTempFBO(framebuffer->renderWidth, framebuffer->renderHeight, Draw::FBO_8888); draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); shaderManager_->DirtyLastShader(); TextureShaderApplier shaderApply(depal, framebuffer->bufferWidth, framebuffer->bufferHeight, framebuffer->renderWidth, framebuffer->renderHeight); shaderApply.ApplyBounds(gstate_c.vertBounds, gstate_c.curTextureXOffset, gstate_c.curTextureYOffset); - shaderApply.Use(drawEngine_); + shaderApply.Use(render_, drawEngine_); - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, clutTexture); - glActiveTexture(GL_TEXTURE0); + render_->BindTexture(3, clutTexture); framebufferManagerGL_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -551,7 +538,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag // Always generate a texture name unless it's a framebuffer, we might need it if the texture is replaced later. if (!replaceImages) { if (!entry->textureName) { - entry->textureName = AllocTextureName(); + entry->textureName = render_->CreateTexture(GL_TEXTURE_2D); } } @@ -615,8 +602,8 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag if (replaced.GetSize(0, w, h)) { if (replaceImages) { // Since we're replacing the texture, we can't replace the image inside. - glDeleteTextures(1, &entry->textureName); - entry->textureName = AllocTextureName(); + render_->DeleteTexture(entry->textureName); + entry->textureName = render_->CreateTexture(GL_TEXTURE_2D); replaceImages = false; } @@ -648,7 +635,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag } } - glBindTexture(GL_TEXTURE_2D, entry->textureName); + // glBindTexture(GL_TEXTURE_2D, entry->textureName); lastBoundTexture = entry->textureName; // Disabled this due to issue #6075: https://github.com/hrydgard/ppsspp/issues/6075 @@ -727,7 +714,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag if (gstate_c.Supports(GPU_SUPPORTS_ANISOTROPY)) { int aniso = 1 << g_Config.iAnisotropyLevel; - float anisotropyLevel = (float) aniso > maxAnisotropyLevel ? maxAnisotropyLevel : (float) aniso; + float anisotropyLevel = aniso; //(float) aniso > maxAnisotropyLevel ? maxAnisotropyLevel : (float) aniso; if (anisotropyLevel > 1.0f) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropyLevel); } @@ -743,16 +730,6 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag CHECK_GL_ERROR_IF_DEBUG(); } -u32 TextureCacheGLES::AllocTextureName() { - if (nameCache_.empty()) { - nameCache_.resize(TEXCACHE_NAME_CACHE_SIZE); - glGenTextures(TEXCACHE_NAME_CACHE_SIZE, &nameCache_[0]); - } - u32 name = nameCache_.back(); - nameCache_.pop_back(); - return name; -} - GLenum TextureCacheGLES::GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const { switch (format) { case GE_TFMT_CLUT4: diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 9e894e2476..559ccf7720 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -21,6 +21,7 @@ #include "gfx_es2/gpu_features.h" #include "gfx/gl_common.h" +#include "thin3d/GLRenderManager.h" #include "GPU/GPUInterface.h" #include "GPU/GPUState.h" #include "GPU/GLES/TextureScalerGLES.h" @@ -31,6 +32,7 @@ class FramebufferManagerGLES; class DepalShaderCacheGLES; class ShaderManagerGLES; class DrawEngineGLES; +class GLRTexture; class TextureCacheGLES : public TextureCacheCommon { public: @@ -52,17 +54,15 @@ public: } void ForgetLastTexture() override { - lastBoundTexture = INVALID_TEX; + lastBoundTexture = nullptr; gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } void InvalidateLastTexture(TexCacheEntry *entry = nullptr) override { if (!entry || entry->textureName == lastBoundTexture) { - lastBoundTexture = INVALID_TEX; + lastBoundTexture = nullptr; } } - u32 AllocTextureName(); - // Only used by Qt UI? bool DecodeTexture(u8 *output, const GPUgstate &state); @@ -87,12 +87,11 @@ private: void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; - std::vector nameCache_; + GLRenderManager *render_; TextureScalerGLES scaler; - u32 lastBoundTexture; - float maxAnisotropyLevel; + GLRTexture *lastBoundTexture; FramebufferManagerGLES *framebufferManagerGL_; DepalShaderCacheGLES *depalShaderCache_; diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 3b9707ca4c..283797b064 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -121,7 +121,7 @@ void FormatDebugOutputARB(char outStr[], size_t outStrSize, GLenum source, GLenu _snprintf(severityStr, 32, severityFmt, severity); - _snprintf(outStr, outStrSize, "OpenGL: %s [source=%s type=%s severity=%s id=%d]", msg, sourceStr, typeStr, severityStr, id); + _snprintf(outStr, outStrSize, "OpenGL: %s [source=%s type=%s severity=%s id=%d]\n", msg, sourceStr, typeStr, severityStr, id); } void DebugCallbackARB(GLenum source, GLenum type, GLuint id, GLenum severity, diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 0ddc148c0d..37084abb05 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -6,12 +6,19 @@ #include "gfx_es2/gpu_features.h" #include "math/dataconv.h" -void GLQueueRunner::CreateDeviceObjects() { +#define TEXCACHE_NAME_CACHE_SIZE 16 +void GLQueueRunner::CreateDeviceObjects() { + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel_); + glGenVertexArrays(1, &globalVAO_); } void GLQueueRunner::DestroyDeviceObjects() { - + if (!nameCache_.empty()) { + glDeleteTextures((GLsizei)nameCache_.size(), &nameCache_[0]); + nameCache_.clear(); + } + glDeleteVertexArrays(1, &globalVAO_); } void GLQueueRunner::RunInitSteps(const std::vector &steps) { @@ -146,10 +153,14 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { } break; } - case GLRInitStepType::CREATE_INPUT_LAYOUT: { GLRInputLayout *layout = step.create_input_layout.inputLayout; + // Nothing to do unless we want to create vertexbuffer objects (GL 4.5) + break; + } + case GLRInitStepType::CREATE_FRAMEBUFFER: + { // TODO break; } @@ -164,8 +175,8 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { CHECK_GL_ERROR_IF_DEBUG(); 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_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST); break; } default: @@ -219,6 +230,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { PerformBindFramebufferAsRenderTarget(step); glEnable(GL_SCISSOR_TEST); + + glBindVertexArray(globalVAO_); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -342,15 +355,20 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { break; } case GLRRenderCommand::STENCIL: - glStencilFunc(c.stencil.func, c.stencil.ref, c.stencil.compareMask); - glStencilOp(c.stencil.sFail, c.stencil.zFail, c.stencil.pass); - glStencilMask(c.stencil.writeMask); + if (c.stencil.enabled) { + glEnable(GL_STENCIL_TEST); + glStencilFunc(c.stencil.func, c.stencil.ref, c.stencil.compareMask); + glStencilOp(c.stencil.sFail, c.stencil.zFail, c.stencil.pass); + glStencilMask(c.stencil.writeMask); + } else { + glDisable(GL_STENCIL_TEST); + } break; case GLRRenderCommand::BINDTEXTURE: { GLint target = c.texture.slot; if (target != activeTexture) { - glActiveTexture(target); + glActiveTexture(GL_TEXTURE0 + target); activeTexture = target; } glBindTexture(c.texture.texture->target, c.texture.texture->texture); @@ -376,6 +394,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glDisableVertexAttribArray(i); } } + attrMask = layout->semanticsMask_; for (int i = 0; i < layout->entries.size(); i++) { auto &entry = layout->entries[i]; glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.inputLayout.offset + entry.offset)); @@ -410,6 +429,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter); + if (c.textureSampler.anisotropy != 0.0f) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy); + } break; case GLRRenderCommand::RASTER: if (c.raster.cullEnable) { @@ -441,6 +463,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glActiveTexture(GL_TEXTURE0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindVertexArray(0); glDisable(GL_SCISSOR_TEST); } @@ -510,3 +533,14 @@ void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) { void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { } + +GLuint GLQueueRunner::AllocTextureName() { + if (nameCache_.empty()) { + nameCache_.resize(TEXCACHE_NAME_CACHE_SIZE); + glGenTextures(TEXCACHE_NAME_CACHE_SIZE, &nameCache_[0]); + } + u32 name = nameCache_.back(); + nameCache_.pop_back(); + return name; +} + diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 810027d461..2d96cf0fae 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -138,6 +138,7 @@ struct GLRRenderData { GLenum wrapT; GLenum magFilter; GLenum minFilter; // also includes mip. GL... + float anisotropy; } textureSampler; struct { GLRViewport vp; @@ -163,6 +164,7 @@ enum class GLRInitStepType : uint8_t { CREATE_PROGRAM, CREATE_BUFFER, CREATE_INPUT_LAYOUT, + CREATE_FRAMEBUFFER, TEXTURE_IMAGE, TEXTURE_SUBDATA, @@ -176,9 +178,6 @@ struct GLRInitStep { struct { GLRTexture *texture; GLenum target; - int width; - int height; - // ... } create_texture; struct { GLRShader *shader; @@ -199,6 +198,9 @@ struct GLRInitStep { struct { GLRInputLayout *inputLayout; } create_input_layout; + struct { + GLRFramebuffer *framebuffer; + } create_framebuffer; struct { GLRBuffer *buffer; int offset; @@ -214,6 +216,7 @@ struct GLRInitStep { int level; int width; int height; + bool linearFilter; uint8_t *data; // owned, delete[]-d } texture_image; }; @@ -312,10 +315,18 @@ private: void ResizeReadbackBuffer(size_t requiredSize); + GLuint globalVAO_; + GLint curFramebuffer_ = 0; // Readback buffer. Currently we only support synchronous readback, so we only really need one. // We size it generously. GLint readbackBuffer_ = 0; int readbackBufferSize_ = 0; + + float maxAnisotropyLevel_; + + GLuint AllocTextureName(); + // Texture name cache. Ripped straight from TextureCacheGLES. + std::vector nameCache_; }; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 1c05cc4577..301418449d 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -28,12 +28,19 @@ GLRenderManager::GLRenderManager() { for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { } + + if (!useThread_) { + queueRunner_.CreateDeviceObjects(); + } } GLRenderManager::~GLRenderManager() { for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { } + if (!useThread_) { + queueRunner_.DestroyDeviceObjects(); + } } void GLRenderManager::ThreadFunc() { @@ -41,6 +48,7 @@ void GLRenderManager::ThreadFunc() { int threadFrame = threadInitFrame_; bool nextFrame = false; bool firstFrame = true; + queueRunner_.CreateDeviceObjects(); while (true) { { if (nextFrame) { @@ -75,6 +83,7 @@ void GLRenderManager::ThreadFunc() { Run(threadFrame); VLOG("PULL: Finished frame %d", threadFrame); } + queueRunner_.DestroyDeviceObjects(); VLOG("PULL: Quitting"); } @@ -365,6 +374,8 @@ void GLPushBuffer::Unmap() { // Here we should simply upload everything to the buffers. // Might be worth trying with size_ instead of offset_, so the driver can replace the whole buffer. // At least if it's close. + if (offset_ > 0 && buffers_[buf_].deviceMemory[0] == 0xCD) + Crash(); render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].deviceMemory, false); writePtr_ = nullptr; } diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index a3ee244b9f..4c08c36e05 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -22,27 +22,8 @@ class GLRInputLayout; class GLRFramebuffer { public: - GLRFramebuffer(int _width, int _height) { - width = _width; - height = _height; - - /* - CreateImage(vulkan_, initCmd, color, width, height, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); - CreateImage(vulkan_, initCmd, depth, width, height, vulkan_->GetDeviceInfo().preferredDepthStencilFormat, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false); - - VkFramebufferCreateInfo fbci{ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO }; - VkImageView views[2]{}; - - fbci.renderPass = renderPass; - fbci.attachmentCount = 2; - fbci.pAttachments = views; - views[0] = color.imageView; - views[1] = depth.imageView; - fbci.width = width; - fbci.height = height; - fbci.layers = 1; - - vkCreateFramebuffer(vulkan_->GetDevice(), &fbci, nullptr, &framebuf);*/ + GLRFramebuffer(int _width, int _height, bool z_stencil) + : width(_width), height(_height), z_stencil_(z_stencil) { } ~GLRFramebuffer() { @@ -57,6 +38,7 @@ public: GLRImage depth{}; int width = 0; int height = 0; + bool z_stencil_; }; // We need to create some custom heap-allocated types so we can forward things that need to be created on the GL thread, before @@ -200,12 +182,10 @@ public: void Wipe(); // Creation commands. These were not needed in Vulkan since there we can do that on the main thread. - GLRTexture *CreateTexture(GLenum target, int w, int h) { + GLRTexture *CreateTexture(GLenum target) { GLRInitStep step{ GLRInitStepType::CREATE_TEXTURE }; step.create_texture.texture = new GLRTexture(); step.create_texture.texture->target = target; - step.create_texture.width = w; - step.create_texture.height = h; initSteps_.push_back(step); return step.create_texture.texture; } @@ -229,6 +209,13 @@ public: return step.create_shader.shader; } + GLRFramebuffer *CreateFramebuffer(int width, int height, bool z_stencil) { + GLRInitStep step{ GLRInitStepType::CREATE_FRAMEBUFFER }; + step.create_framebuffer.framebuffer = new GLRFramebuffer(width, height, z_stencil); + initSteps_.push_back(step); + return step.create_framebuffer.framebuffer; + } + GLRProgram *CreateProgram( std::vector shaders, std::vector semantics, std::vector queries, std::vector initalizers, bool supportDualSource) { @@ -302,7 +289,7 @@ public: initSteps_.push_back(step); } - void TextureImage(GLRTexture *texture, int level, int width, int height, GLenum internalFormat, GLenum format, GLenum type, uint8_t *data) { + void TextureImage(GLRTexture *texture, int level, int width, int height, GLenum internalFormat, GLenum format, GLenum type, uint8_t *data, bool linearFilter = false) { GLRInitStep step{ GLRInitStepType::TEXTURE_IMAGE }; step.texture_image.texture = texture; step.texture_image.data = data; @@ -312,6 +299,7 @@ public: step.texture_image.level = level; step.texture_image.width = width; step.texture_image.height = height; + step.texture_image.linearFilter = linearFilter; initSteps_.push_back(step); } @@ -496,13 +484,14 @@ public: } // Modifies the current texture as per GL specs, not global state. - void SetTextureSampler(GLenum wrapS, GLenum wrapT, GLenum magFilter, GLenum minFilter) { + void SetTextureSampler(GLenum wrapS, GLenum wrapT, GLenum magFilter, GLenum minFilter, float anisotropy) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::TEXTURESAMPLER }; data.textureSampler.wrapS = wrapS; data.textureSampler.wrapT = wrapT; data.textureSampler.magFilter = magFilter; data.textureSampler.minFilter = minFilter; + data.textureSampler.anisotropy = anisotropy; curRenderStep_->commands.push_back(data); } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 1331a34f2d..33a890d90d 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -631,7 +631,7 @@ OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : format_ = desc.format; type_ = desc.type; GLenum target = TypeToTarget(desc.type); - tex_ = render->CreateTexture(target, width_, height_); + tex_ = render->CreateTexture(target); canWrap_ = isPowerOf2(width_) && isPowerOf2(height_); mipLevels_ = desc.mipLevels; @@ -1070,7 +1070,7 @@ void OpenGLContext::ApplySamplers() { } GLenum magFilt = samp->magFilt; GLenum minFilt = tex->HasMips() ? samp->mipMinFilt : samp->minFilt; - renderManager_.SetTextureSampler(wrapS, wrapT, magFilt, minFilt); + renderManager_.SetTextureSampler(wrapS, wrapT, magFilt, minFilt, 0.0f); } } } @@ -1325,6 +1325,9 @@ OpenGLFramebuffer *OpenGLContext::fbo_ext_create(const FramebufferDesc &desc) { Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) { CheckGLExtensions(); + OpenGLFramebuffer *fbo = new OpenGLFramebuffer(); + // fbo->framebuffer = renderManager_.CreateFramebuffer() + #ifndef USING_GLES2 if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) { return fbo_ext_create(desc); @@ -1335,7 +1338,6 @@ Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) { #endif CHECK_GL_ERROR_IF_DEBUG(); - OpenGLFramebuffer *fbo = new OpenGLFramebuffer(); fbo->width = desc.width; fbo->height = desc.height; fbo->colorDepth = desc.colorDepth; @@ -1578,10 +1580,10 @@ void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int s if (channelBits & FB_COLOR_BIT) { aspect |= GL_COLOR_BUFFER_BIT; } else if (channelBits & (FB_STENCIL_BIT | FB_DEPTH_BIT)) { - if (channelBits & FB_STENCIL_BIT) - aspect |= GL_STENCIL_BUFFER_BIT; if (channelBits & FB_DEPTH_BIT) aspect |= GL_DEPTH_BUFFER_BIT; + if (channelBits & FB_STENCIL_BIT) + aspect |= GL_STENCIL_BUFFER_BIT; } renderManager_.CopyFramebuffer(src->framebuffer, GLRect2D{ srcX, srcY, width, height }, dst->framebuffer, GLOffset2D{ dstX, dstY }, aspect); } @@ -1589,30 +1591,34 @@ void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int s bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *fbdst, int dstX1, int dstY1, int dstX2, int dstY2, int channels, FBBlitFilter linearFilter) { OpenGLFramebuffer *src = (OpenGLFramebuffer *)fbsrc; OpenGLFramebuffer *dst = (OpenGLFramebuffer *)fbdst; - GLuint bits = 0; + GLuint aspect = 0; if (channels & FB_COLOR_BIT) - bits |= GL_COLOR_BUFFER_BIT; + aspect |= GL_COLOR_BUFFER_BIT; if (channels & FB_DEPTH_BIT) - bits |= GL_DEPTH_BUFFER_BIT; + aspect |= GL_DEPTH_BUFFER_BIT; if (channels & FB_STENCIL_BIT) - bits |= GL_STENCIL_BUFFER_BIT; + aspect |= GL_STENCIL_BUFFER_BIT; + + renderManager_.BlitFramebuffer(src->framebuffer, GLRect2D{ srcX1, srcY1, srcX2 - srcX1, srcY2 - srcY1 }, dst->framebuffer, GLRect2D{ dstX1, dstY1, dstX2 - dstX1, dstY2 - dstY1 }, aspect, linearFilter == FB_BLIT_LINEAR); + /* // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing // in ES 2.0 that actually separate them anyway of course, so doesn't matter. fbo_bind_fb_target(false, dst->handle); fbo_bind_fb_target(true, src->handle); if (gl_extensions.GLES3 || gl_extensions.ARB_framebuffer_object) { - glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, bits, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST); + glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, aspect, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST); CHECK_GL_ERROR_IF_DEBUG(); #if defined(USING_GLES2) && defined(__ANDROID__) // We only support this extension on Android, it's not even available on PC. return true; } else if (gl_extensions.NV_framebuffer_blit) { - glBlitFramebufferNV(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, bits, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST); + glBlitFramebufferNV(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, aspect, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST); CHECK_GL_ERROR_IF_DEBUG(); #endif // defined(USING_GLES2) && defined(__ANDROID__) return true; } else { return false; - } + }*/ + return true; } void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int color) { From 46e1fbb78856c8304fbf3d4d820134462959507e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 19 Nov 2017 18:22:46 +0100 Subject: [PATCH 011/291] Initial texture work. Bugfix indexed drawing --- GPU/Common/TextureCacheCommon.cpp | 2 +- GPU/GLES/DrawEngineGLES.cpp | 17 ++-- GPU/GLES/FramebufferManagerGLES.cpp | 109 +++++++++---------------- GPU/GLES/GPU_GLES.cpp | 3 - GPU/GLES/TextureCacheGLES.cpp | 111 +++++++------------------- GPU/GLES/TextureCacheGLES.h | 7 +- ext/native/thin3d/GLRenderManager.cpp | 4 +- ext/native/thin3d/GLRenderManager.h | 12 +-- ext/native/thin3d/thin3d_gl.cpp | 3 +- 9 files changed, 91 insertions(+), 177 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index bcfa89ed31..75f9a5d14c 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -383,7 +383,7 @@ void TextureCacheCommon::SetTexture(bool force) { // Exponential backoff up to 512 frames. Textures are often reused. if (entry->numFrames > 32) { // Also, try to add some "randomness" to avoid rehashing several textures the same frame. - entry->framesUntilNextFullHash = std::min(512, entry->numFrames) + (((intptr_t)entry->textureName >> 8) & 15); + entry->framesUntilNextFullHash = std::min(512, entry->numFrames) + (((intptr_t)(entry->textureName) >> 12) & 15); } else { entry->framesUntilNextFullHash = entry->numFrames; } diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index d05489dd92..b7303b05dc 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -181,8 +181,8 @@ void DrawEngineGLES::InitDeviceObjects() { } for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { - frameData_[i].pushVertex = new GLPushBuffer(render_, 1024 * 1024); - frameData_[i].pushIndex = new GLPushBuffer(render_, 512 * 1024); + frameData_[i].pushVertex = new GLPushBuffer(render_, GL_ARRAY_BUFFER, 1024 * 1024); + frameData_[i].pushIndex = new GLPushBuffer(render_, GL_ELEMENT_ARRAY_BUFFER, 512 * 1024); } int vertexSize = sizeof(TransformedVertex); @@ -695,14 +695,7 @@ rotateVBO: } ApplyDrawStateLate(); - - if (gstate_c.Supports(GPU_SUPPORTS_VAO) && vbo == 0) { - vbo = BindBuffer(decoded, dec_->GetDecVtxFmt().stride * indexGen.MaxIndex()); - if (useElements) { - ebo = BindElementBuffer(decIndex, sizeof(short) * indexGen.VertexCount()); - } - } - + LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim); GLRInputLayout *inputLayout = SetupDecFmtForDraw(program, dec_->GetDecVtxFmt()); render_->BindVertexBuffer(vertexBuffer); @@ -777,10 +770,10 @@ rotateVBO: if (drawIndexed) { vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(drawBuffer, maxIndex * sizeof(TransformedVertex), &vertexBuffer); indexBufferOffset = (uint32_t)frameData.pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), &indexBuffer); - render_->BindIndexBuffer(indexBuffer); render_->BindVertexBuffer(vertexBuffer); render_->BindInputLayout(softwareInputLayout_, (void *)(intptr_t)vertexBufferOffset); - render_->DrawIndexed(glprim[prim], numTrans, GL_UNSIGNED_SHORT, inds); + render_->BindIndexBuffer(indexBuffer); + render_->DrawIndexed(glprim[prim], numTrans, GL_UNSIGNED_SHORT, (void *)(intptr_t)indexBufferOffset); } else { vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(drawBuffer, numTrans * sizeof(TransformedVertex), &vertexBuffer); render_->BindVertexBuffer(vertexBuffer); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index fccf90b1f3..854a91e46c 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -347,65 +347,48 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma // TODO: We can just change the texture format and flip some bits around instead of this. // Could share code with the texture cache perhaps. - bool useConvBuf = false; - if (srcPixelFormat != GE_FORMAT_8888 || srcStride != texWidth) { - useConvBuf = true; - u32 neededSize = texWidth * height * 4; - if (!convBuf_ || convBufSize_ < neededSize) { - delete [] convBuf_; - convBuf_ = new u8[neededSize]; - convBufSize_ = neededSize; - } - for (int y = 0; y < height; y++) { - switch (srcPixelFormat) { - case GE_FORMAT_565: - { - const u16 *src = (const u16 *)srcPixels + srcStride * y; - u8 *dst = convBuf_ + 4 * texWidth * y; - ConvertRGBA565ToRGBA8888((u32 *)dst, src, width); - } - break; - - case GE_FORMAT_5551: - { - const u16 *src = (const u16 *)srcPixels + srcStride * y; - u8 *dst = convBuf_ + 4 * texWidth * y; - ConvertRGBA5551ToRGBA8888((u32 *)dst, src, width); - } - break; - - case GE_FORMAT_4444: - { - const u16 *src = (const u16 *)srcPixels + srcStride * y; - u8 *dst = convBuf_ + 4 * texWidth * y; - ConvertRGBA4444ToRGBA8888((u32 *)dst, src, width); - } - break; - - case GE_FORMAT_8888: - { - const u8 *src = srcPixels + srcStride * 4 * y; - u8 *dst = convBuf_ + 4 * texWidth * y; - memcpy(dst, src, 4 * width); - } - break; - - case GE_FORMAT_INVALID: - _dbg_assert_msg_(G3D, false, "Invalid pixelFormat passed to DrawPixels()."); - break; + u32 neededSize = texWidth * height * 4; + u8 *convBuf = new u8[neededSize]; + for (int y = 0; y < height; y++) { + switch (srcPixelFormat) { + case GE_FORMAT_565: + { + const u16 *src = (const u16 *)srcPixels + srcStride * y; + u8 *dst = convBuf + 4 * texWidth * y; + ConvertRGBA565ToRGBA8888((u32 *)dst, src, width); } + break; + + case GE_FORMAT_5551: + { + const u16 *src = (const u16 *)srcPixels + srcStride * y; + u8 *dst = convBuf + 4 * texWidth * y; + ConvertRGBA5551ToRGBA8888((u32 *)dst, src, width); + } + break; + + case GE_FORMAT_4444: + { + const u16 *src = (const u16 *)srcPixels + srcStride * y; + u8 *dst = convBuf + 4 * texWidth * y; + ConvertRGBA4444ToRGBA8888((u32 *)dst, src, width); + } + break; + + case GE_FORMAT_8888: + { + const u8 *src = srcPixels + srcStride * 4 * y; + u8 *dst = convBuf + 4 * texWidth * y; + memcpy(dst, src, 4 * width); + } + break; + + case GE_FORMAT_INVALID: + _dbg_assert_msg_(G3D, false, "Invalid pixelFormat passed to DrawPixels()."); + break; } } - - // Try to skip uploading the unnecessary parts. - if (gstate_c.Supports(GPU_SUPPORTS_UNPACK_SUBIMAGE) && width != texWidth) { - glPixelStorei(GL_UNPACK_ROW_LENGTH, texWidth); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, useConvBuf ? convBuf_ : srcPixels); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, height, GL_RGBA, GL_UNSIGNED_BYTE, useConvBuf ? convBuf_ : srcPixels); - } - CHECK_GL_ERROR_IF_DEBUG(); + render_->TextureImage(drawPixelsTex_, 0, texWidth, height, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, convBuf); } void FramebufferManagerGLES::SetViewport2D(int x, int y, int w, int h) { @@ -979,20 +962,6 @@ void FramebufferManagerGLES::PackFramebufferSync_(VirtualFramebuffer *vfb, int x ConvertFromRGBA8888(dst, packed, vfb->fb_stride, packStride, packWidth, h, vfb->format); } } - - // TODO: Move this into Thin3d. - if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) { -#ifdef USING_GLES2 - // GLES3 doesn't support using GL_READ_FRAMEBUFFER here. - draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); - 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); - } - CHECK_GL_ERROR_IF_DEBUG(); } void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) { diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 594c980f05..8139f142ac 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -300,9 +300,6 @@ void GPU_GLES::CheckGPUFeatures() { if (gl_extensions.OES_texture_npot) features |= GPU_SUPPORTS_OES_TEXTURE_NPOT; - if (gl_extensions.EXT_unpack_subimage) - features |= GPU_SUPPORTS_UNPACK_SUBIMAGE; - if (gl_extensions.EXT_blend_minmax) features |= GPU_SUPPORTS_BLEND_MINMAX; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index b841a32f23..43cbc96914 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -45,10 +45,6 @@ #include #endif -#ifndef GL_UNPACK_ROW_LENGTH -#define GL_UNPACK_ROW_LENGTH 0x0CF2 -#endif - TextureCacheGLES::TextureCacheGLES(Draw::DrawContext *draw) : TextureCacheCommon(draw) { timesInvalidatedAllThisFrame_ = 0; @@ -487,7 +483,7 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16); const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor; - TexCacheEntry::TexStatus alphaStatus = CheckAlpha(clutBuf_, getClutDestFormat(clutFormat), clutTotalColors, clutTotalColors, 1); + TexCacheEntry::TexStatus alphaStatus = CheckAlpha((const uint8_t *)clutBuf_, getClutDestFormat(clutFormat), clutTotalColors, clutTotalColors, 1); gstate_c.SetTextureFullAlpha(alphaStatus == TexCacheEntry::STATUS_ALPHA_FULL); } else { entry->status &= ~TexCacheEntry::STATUS_DEPALETTIZE; @@ -674,35 +670,38 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag LoadTextureLevel(*entry, replaced, 0, replaceImages, scaleFactor, dstFmt); // Mipmapping only enable when texture scaling disable + int texMaxLevel = 0; if (maxLevel > 0 && scaleFactor == 1) { if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) { if (badMipSizes) { // WARN_LOG(G3D, "Bad mipmap for texture sized %dx%dx%d - autogenerating", w, h, (int)format); if (canAutoGen) { - glGenerateMipmap(GL_TEXTURE_2D); + render_->GenerateMipmap(); } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + texMaxLevel = 0; maxLevel = 0; } } else { for (int i = 1; i <= maxLevel; i++) { LoadTextureLevel(*entry, replaced, i, replaceImages, scaleFactor, dstFmt); } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel); + texMaxLevel = maxLevel; } } else { // Avoid PowerVR driver bug if (canAutoGen && w > 1 && h > 1 && !(h > w && (gl_extensions.bugs & BUG_PVR_GENMIPMAP_HEIGHT_GREATER))) { // Really! only seems to fail if height > width // NOTICE_LOG(G3D, "Generating mipmap for texture sized %dx%d%d", w, h, (int)format); - glGenerateMipmap(GL_TEXTURE_2D); + render_->GenerateMipmap(); } else { maxLevel = 0; } } } else if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + texMaxLevel = 0; } + // TODO: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, texMaxLevel); + if (maxLevel == 0) { entry->status |= TexCacheEntry::STATUS_BAD_MIPS; } else { @@ -712,22 +711,8 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag entry->SetAlphaStatus(TexCacheEntry::TexStatus(replaced.AlphaStatus())); } - if (gstate_c.Supports(GPU_SUPPORTS_ANISOTROPY)) { - int aniso = 1 << g_Config.iAnisotropyLevel; - float anisotropyLevel = aniso; //(float) aniso > maxAnisotropyLevel ? maxAnisotropyLevel : (float) aniso; - if (anisotropyLevel > 1.0f) { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropyLevel); - } - } - // This will rebind it, but that's okay. UpdateSamplingParams(*entry, true); - - //glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - //glPixelStorei(GL_PACK_ROW_LENGTH, 0); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - CHECK_GL_ERROR_IF_DEBUG(); } GLenum TextureCacheGLES::GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const { @@ -752,7 +737,7 @@ GLenum TextureCacheGLES::GetDestFormat(GETextureFormat format, GEPaletteFormat c } } -void *TextureCacheGLES::DecodeTextureLevelOld(GETextureFormat format, GEPaletteFormat clutformat, int level, GLenum dstFmt, int scaleFactor, int *bufwout) { +u8 *TextureCacheGLES::DecodeTextureLevelOld(GETextureFormat format, GEPaletteFormat clutformat, int level, GLenum dstFmt, int scaleFactor, int *bufwout) { void *finalBuf = nullptr; u32 texaddr = gstate.getTextureAddress(level); int bufw = GetTextureBufw(level, texaddr, format); @@ -770,26 +755,26 @@ void *TextureCacheGLES::DecodeTextureLevelOld(GETextureFormat format, GEPaletteF decPitch = bufw * pixelSize; } - tmpTexBufRearrange_.resize(std::max(w, bufw) * h); - DecodeTextureLevel((u8 *)tmpTexBufRearrange_.data(), decPitch, format, clutformat, texaddr, level, bufw, true, false, false); - return tmpTexBufRearrange_.data(); + uint8_t *texBuf = new uint8_t[std::max(w, bufw) * h * pixelSize]; + DecodeTextureLevel(texBuf, decPitch, format, clutformat, texaddr, level, bufw, true, false, false); + return texBuf; } -TexCacheEntry::TexStatus TextureCacheGLES::CheckAlpha(const u32 *pixelData, GLenum dstFmt, int stride, int w, int h) { +TexCacheEntry::TexStatus TextureCacheGLES::CheckAlpha(const uint8_t *pixelData, GLenum dstFmt, int stride, int w, int h) { CheckAlphaResult res; switch (dstFmt) { case GL_UNSIGNED_SHORT_4_4_4_4: - res = CheckAlphaABGR4444Basic(pixelData, stride, w, h); + res = CheckAlphaABGR4444Basic((const uint32_t *)pixelData, stride, w, h); break; case GL_UNSIGNED_SHORT_5_5_5_1: - res = CheckAlphaABGR1555Basic(pixelData, stride, w, h); + res = CheckAlphaABGR1555Basic((const uint32_t *)pixelData, stride, w, h); break; case GL_UNSIGNED_SHORT_5_6_5: // Never has any alpha. res = CHECKALPHA_FULL; break; default: - res = CheckAlphaRGBA8888Basic(pixelData, stride, w, h); + res = CheckAlphaRGBA8888Basic((const uint32_t *)pixelData, stride, w, h); break; } @@ -800,7 +785,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r int w = gstate.getTextureWidth(level); int h = gstate.getTextureHeight(level); bool useUnpack = false; - u32 *pixelData; + uint8_t *pixelData; CHECK_GL_ERROR_IF_DEBUG(); @@ -812,10 +797,10 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r if (replaced.GetSize(level, w, h)) { PROFILE_THIS_SCOPE("replacetex"); - tmpTexBufRearrange_.resize(w * h); int bpp = replaced.Format(level) == ReplacedTextureFormat::F_8888 ? 4 : 2; - replaced.Load(level, tmpTexBufRearrange_.data(), bpp * w); - pixelData = tmpTexBufRearrange_.data(); + uint8_t *rearrange = new uint8_t[w * h * bpp]; + replaced.Load(level, rearrange, bpp * w); + pixelData = rearrange; dstFmt = ToGLESFormat(replaced.Format(level)); @@ -825,20 +810,14 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r GEPaletteFormat clutformat = gstate.getClutPaletteFormat(); int bufw; - void *finalBuf = DecodeTextureLevelOld(GETextureFormat(entry.format), clutformat, level, dstFmt, scaleFactor, &bufw); - if (finalBuf == NULL) { + uint8_t *finalBuf = DecodeTextureLevelOld(GETextureFormat(entry.format), clutformat, level, dstFmt, scaleFactor, &bufw); + if (!finalBuf) { return; } - // Can restore these and remove the fixup at the end of DecodeTextureLevel on desktop GL and GLES 3. - if (scaleFactor == 1 && gstate_c.Supports(GPU_SUPPORTS_UNPACK_SUBIMAGE) && w != bufw) { - glPixelStorei(GL_UNPACK_ROW_LENGTH, bufw); - useUnpack = true; - } - // Textures are always aligned to 16 bytes bufw, so this could safely be 4 always. texByteAlign = dstFmt == GL_UNSIGNED_BYTE ? 4 : 2; - pixelData = (u32 *)finalBuf; + pixelData = finalBuf; // We check before scaling since scaling shouldn't invent alpha from a full alpha texture. if ((entry.status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) { @@ -848,8 +827,9 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_UNKNOWN); } - if (scaleFactor > 1) - scaler.Scale(pixelData, dstFmt, w, h, scaleFactor); + // TODO: Scale's buffer management doesn't work. + //if (scaleFactor > 1) + // scaler.Scale((uint32_t *)pixelData, dstFmt, w, h, scaleFactor); if (replacer_.Enabled()) { ReplacedTextureDecodeInfo replacedInfo; @@ -866,8 +846,6 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r } } - glPixelStorei(GL_UNPACK_ALIGNMENT, texByteAlign); - CHECK_GL_ERROR_IF_DEBUG(); GLuint components = dstFmt == GL_UNSIGNED_SHORT_5_6_5 ? GL_RGB : GL_RGBA; @@ -876,7 +854,8 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r if (replaceImages) { PROFILE_THIS_SCOPE("repltex"); - glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, w, h, components2, dstFmt, pixelData); + Crash(); + // glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, w, h, components2, dstFmt, pixelData); } else { PROFILE_THIS_SCOPE("loadtex"); // Avoid misleading errors in texture upload, these are common. @@ -885,37 +864,9 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r WARN_LOG(G3D, "Got an error BEFORE texture upload: %08x (%s)", err, GLEnumToString(err).c_str()); } if (IsFakeMipmapChange()) - glTexImage2D(GL_TEXTURE_2D, 0, components, w, h, 0, components2, dstFmt, pixelData); + render_->TextureImage(entry.textureName, 0, w, h, components, components2, dstFmt, pixelData); else - glTexImage2D(GL_TEXTURE_2D, level, components, w, h, 0, components2, dstFmt, pixelData); - if (!lowMemoryMode_) { - // TODO: We really, really should avoid calling glGetError. - GLenum err = glGetError(); - if (err == GL_OUT_OF_MEMORY) { - WARN_LOG_REPORT(G3D, "Texture cache ran out of GPU memory; switching to low memory mode"); - lowMemoryMode_ = true; - decimationCounter_ = 0; - Decimate(); - // Try again, now that we've cleared out textures in lowMemoryMode_. - glTexImage2D(GL_TEXTURE_2D, level, components, w, h, 0, components2, dstFmt, pixelData); - - I18NCategory *err = GetI18NCategory("Error"); - if (scaleFactor > 1) { - host->NotifyUserMessage(err->T("Warning: Video memory FULL, reducing upscaling and switching to slow caching mode"), 2.0f); - } else { - host->NotifyUserMessage(err->T("Warning: Video memory FULL, switching to slow caching mode"), 2.0f); - } - } else if (err != GL_NO_ERROR) { - // We checked the err anyway, might as well log if there is one. - WARN_LOG(G3D, "Got an error in texture upload: %08x (%s) (components=%s components2=%s dstFmt=%s w=%d h=%d level=%d)", - err, GLEnumToString(err).c_str(), GLEnumToString(components).c_str(), GLEnumToString(components2).c_str(), GLEnumToString(dstFmt).c_str(), - w, h, level); - } - } - } - - if (useUnpack) { - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + render_->TextureImage(entry.textureName, level, w, h, components, components2, dstFmt, pixelData); } } diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 559ccf7720..dcefcfb700 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -80,8 +80,11 @@ private: void UpdateSamplingParams(TexCacheEntry &entry, bool force); void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, bool replaceImages, int scaleFactor, GLenum dstFmt); GLenum GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; - void *DecodeTextureLevelOld(GETextureFormat format, GEPaletteFormat clutformat, int level, GLenum dstFmt, int scaleFactor, int *bufw = 0); - TexCacheEntry::TexStatus CheckAlpha(const u32 *pixelData, GLenum dstFmt, int stride, int w, int h); + + // Caller owns the returned buffer. Delete[]. + u8 *DecodeTextureLevelOld(GETextureFormat format, GEPaletteFormat clutformat, int level, GLenum dstFmt, int scaleFactor, int *bufw = 0); + + TexCacheEntry::TexStatus CheckAlpha(const uint8_t *pixelData, GLenum dstFmt, int stride, int w, int h); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override; void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 301418449d..167359eaeb 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -352,7 +352,7 @@ void GLRenderManager::Wipe() { steps_.clear(); } -GLPushBuffer::GLPushBuffer(GLRenderManager *render, size_t size) : render_(render), buf_(0), offset_(0), size_(size), writePtr_(nullptr) { +GLPushBuffer::GLPushBuffer(GLRenderManager *render, GLuint target, size_t size) : render_(render), target_(target), size_(size) { bool res = AddBuffer(); assert(res); } @@ -383,7 +383,7 @@ void GLPushBuffer::Unmap() { bool GLPushBuffer::AddBuffer() { BufInfo info; info.deviceMemory = new uint8_t[size_]; - info.buffer = render_->CreateBuffer(GL_ARRAY_BUFFER, size_, GL_DYNAMIC_DRAW); + info.buffer = render_->CreateBuffer(target_, size_, GL_DYNAMIC_DRAW); buf_ = buffers_.size(); buffers_.resize(buf_ + 1); buffers_[buf_] = info; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 4c08c36e05..616f932986 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -289,6 +289,7 @@ public: initSteps_.push_back(step); } + // Takes ownership over the data pointer and delete[]-s it. void TextureImage(GLRTexture *texture, int level, int width, int height, GLenum internalFormat, GLenum format, GLenum type, uint8_t *data, bool linearFilter = false) { GLRInitStep step{ GLRInitStepType::TEXTURE_IMAGE }; step.texture_image.texture = texture; @@ -603,7 +604,7 @@ public: }; public: - GLPushBuffer(GLRenderManager *render, size_t size); + GLPushBuffer(GLRenderManager *render, GLuint target, size_t size); ~GLPushBuffer(); void Destroy(); @@ -691,8 +692,9 @@ private: GLRenderManager *render_; std::vector buffers_; - size_t buf_; - size_t offset_; - size_t size_; - uint8_t *writePtr_; + size_t buf_ = 0; + size_t offset_ = 0; + size_t size_ = 0; + uint8_t *writePtr_ = nullptr; + GLuint target_; }; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 33a890d90d..751e839e22 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -539,7 +539,7 @@ OpenGLContext::OpenGLContext() { break; } for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { - frameData_[i].push = new GLPushBuffer(&renderManager_, 64 * 1024); + frameData_[i].push = new GLPushBuffer(&renderManager_, GL_ARRAY_BUFFER, 64 * 1024); } } @@ -1164,7 +1164,6 @@ void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, (void *)offset); renderManager_.Draw(curPipeline_->prim, 0, vertexCount); - renderManager_.BindVertexBuffer(nullptr); #else ApplySamplers(); renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, (void *)vdata); From f3282dcfdad0c2580aa12d6bc75f173fec07a1d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 12 Dec 2017 14:07:52 +0100 Subject: [PATCH 012/291] Delete the gl name cache (might resurrect it on the GLQueueRunner side if needed later). Other cleanup and fixes. --- GPU/Common/FramebufferCommon.h | 2 +- GPU/D3D11/FramebufferManagerD3D11.h | 3 +- GPU/GLES/DrawEngineGLES.cpp | 242 +++------------------------- GPU/GLES/DrawEngineGLES.h | 47 ++---- GPU/GLES/FramebufferManagerGLES.cpp | 176 ++++++++++---------- GPU/GLES/FramebufferManagerGLES.h | 35 ++-- GPU/GLES/GPU_GLES.cpp | 5 +- GPU/GLES/StencilBufferGLES.cpp | 46 +++--- GPU/GLES/TextureCacheGLES.cpp | 10 +- ext/native/thin3d/GLQueueRunner.cpp | 9 -- ext/native/thin3d/GLQueueRunner.h | 2 + ext/native/thin3d/GLRenderManager.h | 13 +- 12 files changed, 185 insertions(+), 405 deletions(-) diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 78005a1126..8545115e86 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -206,7 +206,7 @@ public: return vfb; } } - virtual void RebindFramebuffer(); + void RebindFramebuffer(); std::vector GetFramebufferList(); void CopyDisplayToOutput(); diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index 508e995e52..1bc40e960e 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -58,8 +58,7 @@ public: void BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags); virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; - - virtual void RebindFramebuffer() override; + void RebindFramebuffer(); // TODO: Remove ID3D11Buffer *GetDynamicQuadBuffer() { diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index b7303b05dc..aacc8f7f31 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -91,7 +91,7 @@ #include "GPU/GLES/ShaderManagerGLES.h" #include "GPU/GLES/GPU_GLES.h" -extern const GLuint glprim[8] = { +const GLuint glprim[8] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, @@ -146,17 +146,6 @@ DrawEngineGLES::~DrawEngineGLES() { delete tessDataTransfer; } -void DrawEngineGLES::RestoreVAO() { - if (sharedVao_ != 0) { - glBindVertexArray(sharedVao_); - } else if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { - // Note: this is here because, InitDeviceObjects() is called before GPU_SUPPORTS_VAO is setup. - // So, this establishes it if Supports() returns true and there isn't one yet. - glGenVertexArrays(1, &sharedVao_); - glBindVertexArray(sharedVao_); - } -} - void DrawEngineGLES::DeviceLost() { DestroyDeviceObjects(); } @@ -166,20 +155,6 @@ void DrawEngineGLES::DeviceRestore() { } void DrawEngineGLES::InitDeviceObjects() { - if (bufferNameCache_.empty()) { - bufferNameCache_.resize(VERTEXCACHE_NAME_CACHE_SIZE); - glGenBuffers(VERTEXCACHE_NAME_CACHE_SIZE, &bufferNameCache_[0]); - bufferNameCacheSize_ = 0; - - if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { - glGenVertexArrays(1, &sharedVao_); - } else { - sharedVao_ = 0; - } - } else { - ERROR_LOG(G3D, "Device objects already initialized!"); - } - for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { frameData_[i].pushVertex = new GLPushBuffer(render_, GL_ARRAY_BUFFER, 1024 * 1024); frameData_[i].pushIndex = new GLPushBuffer(render_, GL_ELEMENT_ARRAY_BUFFER, 512 * 1024); @@ -203,18 +178,6 @@ void DrawEngineGLES::DestroyDeviceObjects() { } ClearTrackedVertexArrays(); - if (!bufferNameCache_.empty()) { - glstate.arrayBuffer.unbind(); - glstate.elementArrayBuffer.unbind(); - glDeleteBuffers((GLsizei)bufferNameCache_.size(), &bufferNameCache_[0]); - bufferNameCache_.clear(); - bufferNameInfo_.clear(); - freeSizedBuffers_.clear(); - bufferNameCacheSize_ = 0; - if (sharedVao_ != 0) { - glDeleteVertexArrays(1, &sharedVao_); - } - } render_->DeleteInputLayout(softwareInputLayout_); } @@ -376,11 +339,11 @@ void DrawEngineGLES::DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bindO void DrawEngineGLES::MarkUnreliable(VertexArrayInfo *vai) { vai->status = VertexArrayInfo::VAI_UNRELIABLE; if (vai->vbo) { - FreeBuffer(vai->vbo); + render_->DeleteBuffer(vai->vbo); vai->vbo = 0; } if (vai->ebo) { - FreeBuffer(vai->ebo); + render_->DeleteBuffer(vai->ebo); vai->ebo = 0; } } @@ -420,80 +383,14 @@ void DrawEngineGLES::DecimateTrackedVertexArrays() { vai_.Maintain(); } -GLuint DrawEngineGLES::AllocateBuffer(size_t sz) { - GLuint unused = 0; - - auto freeMatch = freeSizedBuffers_.find(sz); - if (freeMatch != freeSizedBuffers_.end()) { - unused = freeMatch->second; - _assert_(!bufferNameInfo_[unused].used); - - freeSizedBuffers_.erase(freeMatch); - } else { - for (GLuint buf : bufferNameCache_) { - const BufferNameInfo &info = bufferNameInfo_[buf]; - if (info.used) { - continue; - } - - // Just pick the first unused one, we'll have to resize it. - unused = buf; - - // Let's also remove from the free list, if it's there. - if (info.sz != 0) { - auto range = freeSizedBuffers_.equal_range(info.sz); - for (auto it = range.first; it != range.second; ++it) { - if (it->second == buf) { - // It will only be once, so remove and bail. - freeSizedBuffers_.erase(it); - break; - } - } - } - break; - } - } - - if (unused == 0) { - size_t oldSize = bufferNameCache_.size(); - bufferNameCache_.resize(oldSize + VERTEXCACHE_NAME_CACHE_SIZE); - glGenBuffers(VERTEXCACHE_NAME_CACHE_SIZE, &bufferNameCache_[oldSize]); - - unused = bufferNameCache_[oldSize]; - } - - BufferNameInfo &info = bufferNameInfo_[unused]; - - // Record the change in size. - bufferNameCacheSize_ += sz - info.sz; - info.sz = sz; - info.used = true; - return unused; -} - -void DrawEngineGLES::FreeBuffer(GLuint buf) { - // We can reuse buffers by setting new data on them, so let's actually keep it. - auto it = bufferNameInfo_.find(buf); - if (it != bufferNameInfo_.end()) { - it->second.used = false; - it->second.lastFrame = gpuStats.numFlips; - - if (it->second.sz != 0) { - freeSizedBuffers_.insert(std::make_pair(it->second.sz, buf)); - } - } else { - ERROR_LOG(G3D, "Unexpected buffer freed (%d) but not tracked", buf); - } -} - void DrawEngineGLES::FreeVertexArray(VertexArrayInfo *vai) { if (vai->vbo) { - FreeBuffer(vai->vbo); - vai->vbo = 0; + render_->DeleteBuffer(vai->vbo); + vai->vbo = nullptr; } if (vai->ebo) { - FreeBuffer(vai->ebo); - vai->ebo = 0; + render_->DeleteBuffer(vai->ebo); + vai->ebo = nullptr; } } @@ -517,7 +414,6 @@ void DrawEngineGLES::DoFlush() { uint32_t indexBufferOffset = 0; if (vshader->UseHWTransform()) { - GLuint vbo = 0, ebo = 0; int vertexCount = 0; bool useElements = true; @@ -611,31 +507,28 @@ void DrawEngineGLES::DoFlush() { _dbg_assert_msg_(G3D, gstate_c.vertBounds.minV >= gstate_c.vertBounds.maxV, "Should not have checked UVs when caching."); size_t vsz = dec_->GetDecVtxFmt().stride * indexGen.MaxIndex(); - vai->vbo = AllocateBuffer(vsz); - glstate.arrayBuffer.bind(vai->vbo); - glBufferData(GL_ARRAY_BUFFER, vsz, decoded, GL_STATIC_DRAW); + vai->vbo = render_->CreateBuffer(GL_ARRAY_BUFFER, vsz, GL_STATIC_DRAW); + render_->BufferSubdata(vai->vbo, 0, vsz, decoded); + render_->BindVertexBuffer(vai->vbo); // If there's only been one primitive type, and it's either TRIANGLES, LINES or POINTS, // there is no need for the index buffer we built. We can then use glDrawArrays instead // for a very minor speed boost. if (useElements) { size_t esz = sizeof(short) * indexGen.VertexCount(); - vai->ebo = AllocateBuffer(esz); - glstate.elementArrayBuffer.bind(vai->ebo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, esz, (GLvoid *)decIndex, GL_STATIC_DRAW); + vai->ebo = render_->CreateBuffer(GL_ARRAY_BUFFER, esz, GL_STATIC_DRAW); + render_->BufferSubdata(vai->ebo, 0, esz, (uint8_t *)decIndex, false); } else { vai->ebo = 0; - glstate.elementArrayBuffer.bind(vai->ebo); + render_->BindIndexBuffer(vai->ebo); } } else { gpuStats.numCachedDrawCalls++; - glstate.arrayBuffer.bind(vai->vbo); - glstate.elementArrayBuffer.bind(vai->ebo); useElements = vai->ebo ? true : false; gpuStats.numCachedVertsDrawn += vai->numVerts; gstate_c.vertexFullAlpha = vai->flags & VAI_FLAG_VERTEXFULLALPHA; } - vbo = vai->vbo; - ebo = vai->ebo; + vertexBuffer = vai->vbo; + indexBuffer = vai->ebo; vertexCount = vai->numVerts; prim = static_cast(vai->prim); break; @@ -650,10 +543,8 @@ void DrawEngineGLES::DoFlush() { } gpuStats.numCachedDrawCalls++; gpuStats.numCachedVertsDrawn += vai->numVerts; - vbo = vai->vbo; - ebo = vai->ebo; - glstate.arrayBuffer.bind(vbo); - glstate.elementArrayBuffer.bind(ebo); + vertexBuffer = vai->vbo; + indexBuffer = vai->ebo; vertexCount = vai->numVerts; prim = static_cast(vai->prim); @@ -843,108 +734,12 @@ rotateVBO: CHECK_GL_ERROR_IF_DEBUG(); } -GLuint DrawEngineGLES::BindBuffer(const void *p, size_t sz) { - // Get a new buffer each time we need one. - GLuint buf = AllocateBuffer(sz); - glstate.arrayBuffer.bind(buf); - - // These aren't used more than once per frame, so let's use GL_STREAM_DRAW. - glBufferData(GL_ARRAY_BUFFER, sz, p, GL_STREAM_DRAW); - buffersThisFrame_.push_back(buf); - - return buf; -} - -GLuint DrawEngineGLES::BindBuffer(const void *p1, size_t sz1, const void *p2, size_t sz2) { - GLuint buf = AllocateBuffer(sz1 + sz2); - glstate.arrayBuffer.bind(buf); - - glBufferData(GL_ARRAY_BUFFER, sz1 + sz2, nullptr, GL_STREAM_DRAW); - glBufferSubData(GL_ARRAY_BUFFER, 0, sz1, p1); - glBufferSubData(GL_ARRAY_BUFFER, sz1, sz2, p2); - buffersThisFrame_.push_back(buf); - - return buf; -} - -GLuint DrawEngineGLES::BindElementBuffer(const void *p, size_t sz) { - GLuint buf = AllocateBuffer(sz); - glstate.elementArrayBuffer.bind(buf); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sz, p, GL_STREAM_DRAW); - buffersThisFrame_.push_back(buf); - - return buf; -} - -void DrawEngineGLES::DecimateBuffers() { - for (GLuint buf : buffersThisFrame_) { - FreeBuffer(buf); - } - buffersThisFrame_.clear(); - - if (--bufferDecimationCounter_ <= 0) { - bufferDecimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; - } else { - return; - } - - // Let's not keep too many around, will eat up memory. - // First check if there's any to free, and only check if it seems somewhat full. - bool hasOld = false; - if (bufferNameCacheSize_ > VERTEXCACHE_NAME_CACHE_FULL_BYTES) { - for (GLuint buf : bufferNameCache_) { - const BufferNameInfo &info = bufferNameInfo_[buf]; - const int age = gpuStats.numFlips - info.lastFrame; - if (!info.used && age > VERTEXCACHE_NAME_CACHE_MAX_AGE) { - hasOld = true; - break; - } - } - } - - if (hasOld) { - // Okay, it is. Let's rebuild the array. - std::vector toFree; - std::vector toKeep; - - toKeep.reserve(bufferNameCache_.size()); - - for (size_t i = 0, n = bufferNameCache_.size(); i < n; ++i) { - const GLuint buf = bufferNameCache_[i]; - const BufferNameInfo &info = bufferNameInfo_[buf]; - const int age = gpuStats.numFlips - info.lastFrame; - if (!info.used && age > VERTEXCACHE_NAME_CACHE_MAX_AGE) { - toFree.push_back(buf); - bufferNameCacheSize_ -= bufferNameInfo_[buf].sz; - bufferNameInfo_.erase(buf); - - // If we've removed all we want to this round, keep the rest and abort. - if (toFree.size() >= VERTEXCACHE_NAME_DECIMATION_MAX && i + 1 < bufferNameCache_.size()) { - toKeep.insert(toKeep.end(), bufferNameCache_.begin() + i + 1, bufferNameCache_.end()); - break; - } - } else { - toKeep.push_back(buf); - } - } - - if (!toFree.empty()) { - bufferNameCache_ = toKeep; - // TODO: Rebuild? - freeSizedBuffers_.clear(); - - glstate.arrayBuffer.unbind(); - glstate.elementArrayBuffer.unbind(); - glDeleteBuffers((GLsizei)toFree.size(), &toFree[0]); - } - } -} - bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const { return decJitCache_->IsInSpace(ptr); } void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) { + /* #ifndef USING_GLES2 if (isAllowTexture1D_) { // Position @@ -1041,4 +836,5 @@ void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float } glActiveTexture(GL_TEXTURE0); CHECK_GL_ERROR_IF_DEBUG(); + */ } diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 2ed6046b96..9fd2a6080d 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -61,8 +61,8 @@ class VertexArrayInfo { public: VertexArrayInfo() { status = VAI_NEW; - vbo = 0; - ebo = 0; + vbo = nullptr; + ebo = nullptr; prim = GE_PRIM_INVALID; numDraws = 0; numFrames = 0; @@ -82,8 +82,8 @@ public: ReliableHashType hash; u32 minihash; - u32 vbo; - u32 ebo; + GLRBuffer *vbo; + GLRBuffer *ebo; // Precalculated parameter for drawRangeElements u16 numVerts; @@ -119,7 +119,6 @@ public: void SetFragmentTestCache(FragmentTestCacheGLES *testCache) { fragmentTestCache_ = testCache; } - void RestoreVAO(); void DeviceLost(); void DeviceRestore(); @@ -151,10 +150,12 @@ public: SubmitPrim(verts, inds, prim, vertexCount, vertType, bytesRead); } - GLuint BindBuffer(const void *p, size_t sz); - GLuint BindBuffer(const void *p1, size_t sz1, const void *p2, size_t sz2); - GLuint BindElementBuffer(const void *p, size_t sz); - void DecimateBuffers(); + GLPushBuffer *GetPushVertexBuffer() { + return frameData_[render_->GetCurFrame()].pushVertex; + } + GLPushBuffer *GetPushIndexBuffer() { + return frameData_[render_->GetCurFrame()].pushIndex; + } void ClearInputLayoutMap(); @@ -171,8 +172,6 @@ private: void DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bindOffset, GLRBuffer **buf); - GLuint AllocateBuffer(size_t sz); - void FreeBuffer(GLuint buf); void FreeVertexArray(VertexArrayInfo *vai); void MarkUnreliable(VertexArrayInfo *vai); @@ -188,23 +187,7 @@ private: DenseHashMap inputLayoutMap_; GLRInputLayout *softwareInputLayout_ = nullptr; - - // Vertex buffer objects - // Element buffer objects - struct BufferNameInfo { - BufferNameInfo() : sz(0), used(false), lastFrame(0) {} - - size_t sz; - bool used; - int lastFrame; - }; GLRenderManager *render_; - std::vector bufferNameCache_; - std::multimap freeSizedBuffers_; - std::unordered_map bufferNameInfo_; - std::vector buffersThisFrame_; - size_t bufferNameCacheSize_ = 0; - GLuint sharedVao_ = 0; // Other ShaderManagerGLES *shaderManager_ = nullptr; @@ -218,15 +201,11 @@ private: // Hardware tessellation class TessellationDataTransferGLES : public TessellationDataTransfer { private: - int data_tex[3]; + GLRTexture *data_tex[3]{}; bool isAllowTexture1D_; public: - TessellationDataTransferGLES(bool isAllowTexture1D) : TessellationDataTransfer(), data_tex(), isAllowTexture1D_(isAllowTexture1D) { - glGenTextures(3, (GLuint*)data_tex); - } - ~TessellationDataTransferGLES() { - glDeleteTextures(3, (GLuint*)data_tex); - } + TessellationDataTransferGLES(bool isAllowTexture1D) : TessellationDataTransfer(), isAllowTexture1D_(isAllowTexture1D) { } + ~TessellationDataTransferGLES() { } void SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) override; }; }; diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 854a91e46c..52c2d4390f 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -42,7 +42,6 @@ #include "GPU/Common/TextureDecoder.h" #include "GPU/Common/FramebufferCommon.h" #include "GPU/Debugger/Stepping.h" -#include "ext/native/gfx/GLStateCache.h" #include "GPU/GLES/FramebufferManagerGLES.h" #include "GPU/GLES/TextureCacheGLES.h" #include "GPU/GLES/DrawEngineGLES.h" @@ -103,13 +102,14 @@ void FramebufferManagerGLES::CompileDraw2DProgram() { static std::string vs_code, fs_code; vs_code = ApplyGLSLPrelude(basic_vs, GL_VERTEX_SHADER); fs_code = ApplyGLSLPrelude(tex_fs, GL_FRAGMENT_SHADER); - draw2dprogram_ = glsl_create_source(vs_code.c_str(), fs_code.c_str(), &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); - } + std::vector shaders; + GLRShader *vs = render_->CreateShader(GL_VERTEX_SHADER, vs_code); + GLRShader *fs = render_->CreateShader(GL_FRAGMENT_SHADER, fs_code); + std::vector queries; + queries.push_back({ &u_draw2d_tex, "u_tex" }); + std::vector initializers; + initializers.push_back({ &u_draw2d_tex, 0 }); + draw2dprogram_ = render_->CreateProgram(shaders, {}, queries, initializers, false); CompilePostShader(); } } @@ -156,7 +156,26 @@ void FramebufferManagerGLES::CompilePostShader() { } if (!translationFailed) { - postShaderProgram_ = glsl_create_source(vshader.c_str(), fshader.c_str(), &errorString); + SetNumExtraFBOs(1); + + std::vector shaders; + shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vshader)); + shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, fshader)); + std::vector queries; + queries.push_back({ &u_postShaderTex, "tex" }); + queries.push_back({ &deltaLoc_, "u_texelDelta" }); + queries.push_back({ &pixelDeltaLoc_, "u_pixelDelta" }); + queries.push_back({ &timeLoc_, "u_time" }); + queries.push_back({ &videoLoc_, "u_video" }); + + std::vector inits; + inits.push_back({ &u_postShaderTex, 0, 0 }); + postShaderProgram_ = render_->CreateProgram(shaders, {}, queries, inits, false); + render_->SetUniformI1(&u_postShaderTex, 0); + + for (auto iter : shaders) { + render_->DeleteShader(iter); + } } else { ERROR_LOG(FRAMEBUF, "Failed to translate post shader!"); } @@ -194,13 +213,6 @@ void FramebufferManagerGLES::CompilePostShader() { } 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"); - videoLoc_ = glsl_uniform_loc(postShaderProgram_, "u_video"); usePostShader_ = true; } } else { @@ -211,7 +223,7 @@ void FramebufferManagerGLES::CompilePostShader() { } void FramebufferManagerGLES::Bind2DShader() { - glsl_bind(draw2dprogram_); + render_->BindProgram(draw2dprogram_); } void FramebufferManagerGLES::BindPostShader(const PostShaderUniforms &uniforms) { @@ -219,20 +231,20 @@ void FramebufferManagerGLES::BindPostShader(const PostShaderUniforms &uniforms) if (!postShaderProgram_) { CompileDraw2DProgram(); } - - glsl_bind(postShaderProgram_); + render_->BindProgram(postShaderProgram_); if (deltaLoc_ != -1) - glUniform2f(deltaLoc_, uniforms.texelDelta[0], uniforms.texelDelta[1]); + render_->SetUniformF(&deltaLoc_, 2, uniforms.texelDelta); if (pixelDeltaLoc_ != -1) - glUniform2f(pixelDeltaLoc_, uniforms.pixelDelta[0], uniforms.pixelDelta[1]); + render_->SetUniformF(&pixelDeltaLoc_, 2, uniforms.pixelDelta); if (timeLoc_ != -1) - glUniform4fv(timeLoc_, 1, uniforms.time); + render_->SetUniformF(&timeLoc_, 4, uniforms.time); if (videoLoc_ != -1) - glUniform1f(videoLoc_, uniforms.video); + render_->SetUniformF(&videoLoc_, 1, &uniforms.video); } -FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) : +FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render) : FramebufferManagerCommon(draw), + render_(render), drawPixelsTex_(0), drawPixelsTexFormat_(GE_FORMAT_INVALID), convBuf_(nullptr), @@ -275,15 +287,25 @@ void FramebufferManagerGLES::SetDrawEngine(DrawEngineGLES *td) { void FramebufferManagerGLES::CreateDeviceObjects() { CompileDraw2DProgram(); + + std::vector entries; + entries.push_back({ 0, 3, GL_FLOAT, GL_FALSE, sizeof(Simple2DVertex), offsetof(Simple2DVertex, pos) }); + entries.push_back({ 0, 2, GL_FLOAT, GL_FALSE, sizeof(Simple2DVertex), offsetof(Simple2DVertex, uv) }); + simple2DInputLayout_ = render_->CreateInputLayout(entries); } void FramebufferManagerGLES::DestroyDeviceObjects() { + if (simple2DInputLayout_) { + render_->DeleteInputLayout(simple2DInputLayout_); + simple2DInputLayout_ = nullptr; + } + if (draw2dprogram_) { - glsl_destroy(draw2dprogram_); + render_->DeleteProgram(draw2dprogram_); draw2dprogram_ = nullptr; } if (postShaderProgram_) { - glsl_destroy(postShaderProgram_); + render_->DeleteProgram(postShaderProgram_); postShaderProgram_ = nullptr; } if (drawPixelsTex_) { @@ -291,7 +313,7 @@ void FramebufferManagerGLES::DestroyDeviceObjects() { drawPixelsTex_ = 0; } if (stencilUploadProgram_) { - glsl_destroy(stencilUploadProgram_); + render_->DeleteProgram(stencilUploadProgram_); stencilUploadProgram_ = nullptr; } } @@ -329,15 +351,10 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma drawPixelsTexW_ = texWidth; drawPixelsTexH_ = height; - /* - // 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); + render_->BindTexture(0, drawPixelsTex_); + render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); + /* glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); */ drawPixelsTexFormat_ = srcPixelFormat; @@ -392,7 +409,7 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma } void FramebufferManagerGLES::SetViewport2D(int x, int y, int w, int h) { - glstate.viewport.set(x, y, w, h); + render_->SetViewport({ (float)x, (float)y, (float)w, (float)h, 0.0f, 1.0f }); } // x, y, w, h are relative coordinates against destW/destH, which is not very intuitive. @@ -405,7 +422,7 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float u0,v1, }; - static const GLushort indices[4] = {0,1,3,2}; + static const GLushort indices[4] = { 0,1,3,2 }; if (uvRotation != ROTATION_LOCKED_HORIZONTAL) { float temp[8]; @@ -424,9 +441,9 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float float pos[12] = { x,y,0, - x+w,y,0, - x+w,y+h,0, - x,y+h,0 + x + w,y,0, + x + w,y + h,0, + x,y + h,0 }; float invDestW = 1.0f / (destW * 0.5f); @@ -438,11 +455,9 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float // Upscaling postshaders doesn't look well with linear if (flags & DRAWTEX_LINEAR) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); } const GLSLProgram *program = glsl_get_program(); @@ -450,30 +465,23 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float ERROR_LOG(FRAMEBUF, "Trying to DrawActiveTexture() without a program"); return; } + Simple2DVertex verts[4]; + memcpy(verts[0].pos, &pos[0], 12); + memcpy(verts[1].pos, &pos[3], 12); + memcpy(verts[3].pos, &pos[6], 12); + memcpy(verts[2].pos, &pos[9], 12); + memcpy(verts[0].uv, &texCoords[0], 8); + memcpy(verts[1].uv, &texCoords[2], 8); + memcpy(verts[3].uv, &texCoords[4], 8); + memcpy(verts[2].uv, &texCoords[6], 8); - glEnableVertexAttribArray(program->a_position); - glEnableVertexAttribArray(program->a_texcoord0); - if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { - drawEngineGL_->BindBuffer(pos, sizeof(pos), texCoords, sizeof(texCoords)); - drawEngineGL_->BindElementBuffer(indices, sizeof(indices)); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, 0); - glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, (void *)sizeof(pos)); - glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0); - } else { - glstate.arrayBuffer.unbind(); - glstate.elementArrayBuffer.unbind(); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos); - glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, texCoords); - glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices); - } - glDisableVertexAttribArray(program->a_position); - glDisableVertexAttribArray(program->a_texcoord0); -} - -void FramebufferManagerGLES::RebindFramebuffer() { - FramebufferManagerCommon::RebindFramebuffer(); - if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE) - glstate.viewport.restore(); + uint32_t bindOffset; + GLRBuffer *buffer; + void *dest = drawEngineGL_->GetPushVertexBuffer()->Push(sizeof(verts), &bindOffset, &buffer); + memcpy(dest, verts, sizeof(verts)); + render_->BindVertexBuffer(buffer); + render_->BindInputLayout(simple2DInputLayout_, (void *)(intptr_t)bindOffset); + render_->Draw(GL_TRIANGLE_STRIP, 0, 4); } void FramebufferManagerGLES::ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) { @@ -514,17 +522,15 @@ void FramebufferManagerGLES::BlitFramebufferDepth(VirtualFramebuffer *src, Virtu if (gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT)) { // Let's only do this if not clearing depth. - glstate.scissorTest.force(false); draw_->BlitFramebuffer(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, Draw::FB_DEPTH_BIT, Draw::FB_BLIT_NEAREST); dst->last_frame_depth_updated = gpuStats.numFlips; - glstate.scissorTest.restore(); } } } void FramebufferManagerGLES::BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags) { if (!framebuffer->fbo || !useBufferedRendering_) { - glBindTexture(GL_TEXTURE_2D, 0); + render_->BindTexture(0, nullptr); gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE; return; } @@ -691,7 +697,6 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, } } - glstate.scissorTest.force(false); if (useBlit) { draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, Draw::FB_COLOR_BIT, Draw::FB_BLIT_NEAREST); } else { @@ -701,38 +706,21 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, // 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); + render_->SetViewport({ 0, 0, (float)dst->renderWidth, (float)dst->renderHeight, 0, 1.0f }); + render_->SetStencilDisabled(); + render_->SetDepth(false, false, GL_ALWAYS); + render_->SetNoBlendAndMask(0xF); // 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; - glsl_bind(draw2dprogram_); + render_->BindProgram(draw2dprogram_); DrawActiveTexture(dstX1, dstY1, w * dstXFactor, h, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST); - glBindTexture(GL_TEXTURE_2D, 0); textureCacheGL_->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(); } - glstate.scissorTest.restore(); + gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_RASTER_STATE); CHECK_GL_ERROR_IF_DEBUG(); } diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 42d675ebe9..57111e3fa2 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -51,7 +51,7 @@ struct AsyncPBO { class FramebufferManagerGLES : public FramebufferManagerCommon { public: - FramebufferManagerGLES(Draw::DrawContext *draw); + FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render); ~FramebufferManagerGLES(); void SetTextureCache(TextureCacheGLES *tc); @@ -82,7 +82,6 @@ public: bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; - virtual void RebindFramebuffer() override; void DeviceRestore(Draw::DrawContext *draw); @@ -104,7 +103,6 @@ private: void Bind2DShader() override; void BindPostShader(const PostShaderUniforms &uniforms) override; void CompileDraw2DProgram(); - void DestroyDraw2DProgram(); void CompilePostShader(); void PackFramebufferAsync_(VirtualFramebuffer *vfb); // Not used under ES currently @@ -121,19 +119,34 @@ private: u8 *convBuf_; u32 convBufSize_; - GLSLProgram *draw2dprogram_ = nullptr; - GLSLProgram *postShaderProgram_ = nullptr; - GLSLProgram *stencilUploadProgram_ = nullptr; - int plainColorLoc_; - int videoLoc_; - int timeLoc_; - int pixelDeltaLoc_; - int deltaLoc_; + GLRProgram *draw2dprogram_ = nullptr; + GLRProgram *postShaderProgram_ = nullptr; + + + GLRProgram *stencilUploadProgram_ = nullptr; + int u_stencilUploadTex = -1; + int u_stencilValue = -1; + int u_postShaderTex = -1; + + // Cached uniform locs + int u_draw2d_tex = -1; + + int plainColorLoc_ = -1; + int videoLoc_ = -1; + int timeLoc_ = -1; + int pixelDeltaLoc_ = -1; + int deltaLoc_ = -1; TextureCacheGLES *textureCacheGL_; ShaderManagerGLES *shaderManagerGL_; DrawEngineGLES *drawEngineGL_; + struct Simple2DVertex { + float pos[3]; + float uv[2]; + }; + GLRInputLayout *simple2DInputLayout_; + // Not used under ES currently. AsyncPBO *pixelBufObj_; //this isn't that large u8 currentPBO_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 8139f142ac..be88cda194 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -86,7 +86,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) GLRenderManager *render = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); shaderManagerGL_ = new ShaderManagerGLES(render); - framebufferManagerGL_ = new FramebufferManagerGLES(draw); + framebufferManagerGL_ = new FramebufferManagerGLES(draw, render); framebufferManager_ = framebufferManagerGL_; textureCacheGL_ = new TextureCacheGLES(draw); textureCache_ = textureCacheGL_; @@ -163,7 +163,6 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) // Some of our defaults are different from hw defaults, let's assert them. // We restore each frame anyway, but here is convenient for tests. glstate.Restore(); - drawEngine_.RestoreVAO(); textureCacheGL_->NotifyConfigChanged(); // Load shader cache. @@ -498,7 +497,6 @@ void GPU_GLES::UpdateCmdInfo() { } void GPU_GLES::ReapplyGfxState() { - drawEngine_.RestoreVAO(); glstate.Restore(); GPUCommon::ReapplyGfxState(); } @@ -509,7 +507,6 @@ void GPU_GLES::BeginFrame() { textureCacheGL_->StartFrame(); drawEngine_.DecimateTrackedVertexArrays(); - drawEngine_.DecimateBuffers(); depalShaderCache_.Decimate(); fragmentTestCache_.Decimate(); diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 01dfcf254e..15da119330 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -126,26 +126,32 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe static std::string vs_code, fs_code; vs_code = ApplyGLSLPrelude(stencil_vs, GL_VERTEX_SHADER); fs_code = ApplyGLSLPrelude(stencil_fs, GL_FRAGMENT_SHADER); - stencilUploadProgram_ = glsl_create_source(vs_code.c_str(), fs_code.c_str(), &errorString); + std::vector shaders; + shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vs_code)); + shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fs_code)); + std::vector queries; + queries.push_back({ &u_stencilUploadTex, "tex" }); + std::vector inits; + inits.push_back({ &u_stencilUploadTex, 0, 0 }); + stencilUploadProgram_ = render_->CreateProgram(shaders, {}, queries, inits, false); + for (auto iter : shaders) { + render_->DeleteShader(iter); + } if (!stencilUploadProgram_) { ERROR_LOG_REPORT(G3D, "Failed to compile stencilUploadProgram! This shouldn't happen.\n%s", errorString.c_str()); } else { - glsl_bind(stencilUploadProgram_); + render_->BindProgram(stencilUploadProgram_); } - - GLint u_tex = glsl_uniform_loc(stencilUploadProgram_, "tex"); - glUniform1i(u_tex, 0); } else { - glsl_bind(stencilUploadProgram_); + render_->BindProgram(stencilUploadProgram_); } shaderManagerGL_->DirtyLastShader(); DisableState(); - glstate.colorMask.set(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + render_->SetNoBlendAndMask(0x8); glstate.stencilTest.enable(); glstate.stencilOp.set(GL_REPLACE, GL_REPLACE, GL_REPLACE); - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE); bool useBlit = gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT); @@ -164,43 +170,41 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe } else if (dstBuffer->fbo) { draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }); } - glViewport(0, 0, w, h); - gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE); + render_->SetViewport({ 0, 0, (float)w, (float)h, 0.0f, 1.0f }); float u1 = 1.0f; float v1 = 1.0f; MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight, u1, v1); textureCacheGL_->ForgetLastTexture(); - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); + render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT); + render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, 0xFF, 0xFF, 0xFF); - glstate.stencilFunc.set(GL_ALWAYS, 0xFF, 0xFF); - - GLint u_stencilValue = glsl_uniform_loc(stencilUploadProgram_, "u_stencilValue"); for (int i = 1; i < values; i += i) { if (!(usedBits & i)) { // It's already zero, let's skip it. continue; } if (dstBuffer->format == GE_FORMAT_4444) { - glstate.stencilMask.set((i << 4) | i); - glUniform1f(u_stencilValue, i * (16.0f / 255.0f)); + render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, (i << 4) | i, 0xFF, 0xFF); + render_->SetUniformF1(&u_stencilValue, i * (16.0f / 255.0f)); } else if (dstBuffer->format == GE_FORMAT_5551) { glstate.stencilMask.set(0xFF); - glUniform1f(u_stencilValue, i * (128.0f / 255.0f)); + render_->SetUniformF1(&u_stencilValue, i * (128.0f / 255.0f)); } else { - glstate.stencilMask.set(i); - glUniform1f(u_stencilValue, i * (1.0f / 255.0f)); + render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, i, 0xFF, 0xFF); + render_->SetUniformF1(&u_stencilValue, i * (1.0f / 255.0f)); } DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST); } - glstate.stencilMask.set(0xFF); + render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, 0xFF, 0xFF, 0xFF); if (useBlit) { draw_->BlitFramebuffer(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, Draw::FB_STENCIL_BIT, Draw::FB_BLIT_NEAREST); } + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); + RebindFramebuffer(); return true; } diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 43cbc96914..307b208342 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -401,6 +401,7 @@ public: void Use(GLRenderManager *render, DrawEngineGLES *transformDraw) { render->BindProgram(shader_->program); + /* // Restore will rebind all of the state below. if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { static const GLubyte indices[4] = { 0, 1, 3, 2 }; @@ -412,11 +413,12 @@ public: } glEnableVertexAttribArray(shader_->a_position); glEnableVertexAttribArray(shader_->a_texcoord0); + */ } void Shade() { static const GLubyte indices[4] = { 0, 1, 3, 2 }; - + /* glstate.blend.force(false); glstate.colorMask.force(true, true, true, true); glstate.scissorTest.force(false); @@ -441,6 +443,7 @@ public: glDisableVertexAttribArray(shader_->a_texcoord0); glstate.Restore(); + */ } protected: @@ -473,8 +476,7 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram render_->BindTexture(3, clutTexture); framebufferManagerGL_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); shaderApply.Shade(); @@ -496,8 +498,6 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram framebufferManagerGL_->RebindFramebuffer(); SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); - CHECK_GL_ERROR_IF_DEBUG(); - InvalidateLastTexture(); } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 37084abb05..42b25e040f 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -99,16 +99,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { break; } - // Auto-initialize samplers. glUseProgram(program->program); - for (int i = 0; i < 4; i++) { - char temp[256]; - sprintf(temp, "Sampler%i", i); - int samplerLoc = glGetUniformLocation(program->program, temp); - if (samplerLoc != -1) { - glUniform1i(samplerLoc, i); - } - } // Query all the uniforms. for (int i = 0; i < program->queries_.size(); i++) { diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 2d96cf0fae..f6ddf68ef9 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -318,6 +318,8 @@ private: GLuint globalVAO_; GLint curFramebuffer_ = 0; + int curFBWidth_; + int curFBHeight_; // Readback buffer. Currently we only support synchronous readback, so we only really need one. // We size it generously. diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 616f932986..19c82ee043 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -122,7 +122,7 @@ public: glDeleteBuffers(1, &buffer); } } - GLuint buffer; + GLuint buffer = 0; GLuint target_; private: }; @@ -216,6 +216,8 @@ public: return step.create_framebuffer.framebuffer; } + // Can't replace uniform initializers with direct calls to SetUniform() etc because there might + // not be an active render pass. GLRProgram *CreateProgram( std::vector shaders, std::vector semantics, std::vector queries, std::vector initalizers, bool supportDualSource) { @@ -398,6 +400,15 @@ public: curRenderStep_->commands.push_back(data); } + void SetUniformF1(GLint *loc, const float udata) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; + data.uniform4.loc = loc; + data.uniform4.count = 1; + memcpy(data.uniform4.v, &udata, sizeof(float)); + curRenderStep_->commands.push_back(data); + } + void SetUniformF(const char *name, int count, const float *udata) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; From 51f467a7b3a23e63e9230346b6aa6502ba347022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 12 Dec 2017 15:04:46 +0100 Subject: [PATCH 013/291] Kill off the GL state cache --- CMakeLists.txt | 2 - GPU/GLES/DepalettizeShaderGLES.cpp | 1 - GPU/GLES/DrawEngineGLES.cpp | 8 +- GPU/GLES/DrawEngineGLES.h | 2 +- GPU/GLES/FragmentTestCacheGLES.h | 1 - GPU/GLES/FramebufferManagerGLES.cpp | 1 + GPU/GLES/GPU_GLES.cpp | 18 -- GPU/GLES/ShaderManagerGLES.cpp | 2 +- GPU/GLES/StateMappingGLES.cpp | 21 +-- GPU/GLES/StencilBufferGLES.cpp | 19 +- GPU/GLES/TextureCacheGLES.cpp | 5 +- Qt/Debugger/debugger_memorytex.cpp | 1 - ext/native/Android.mk | 1 - ext/native/gfx/GLStateCache.cpp | 52 ----- ext/native/gfx/GLStateCache.h | 283 ---------------------------- ext/native/native.vcxproj | 2 - ext/native/native.vcxproj.filters | 8 +- ext/native/thin3d/GLQueueRunner.cpp | 49 +++-- ext/native/thin3d/GLQueueRunner.h | 21 ++- ext/native/thin3d/GLRenderManager.h | 39 ++-- ext/native/thin3d/thin3d.h | 2 +- ext/native/thin3d/thin3d_gl.cpp | 9 +- 22 files changed, 110 insertions(+), 437 deletions(-) delete mode 100644 ext/native/gfx/GLStateCache.cpp delete mode 100644 ext/native/gfx/GLStateCache.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a1ae75c2d..b60032d8f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -887,8 +887,6 @@ add_library(native STATIC ext/native/file/vfs.h ext/native/file/zip_read.cpp ext/native/file/zip_read.h - ext/native/gfx/GLStateCache.cpp - ext/native/gfx/GLStateCache.h ext/native/gfx/gl_common.h ext/native/gfx/gl_debug_log.cpp ext/native/gfx/gl_debug_log.h diff --git a/GPU/GLES/DepalettizeShaderGLES.cpp b/GPU/GLES/DepalettizeShaderGLES.cpp index 7e56ce8525..b4eff02b9d 100644 --- a/GPU/GLES/DepalettizeShaderGLES.cpp +++ b/GPU/GLES/DepalettizeShaderGLES.cpp @@ -23,7 +23,6 @@ #include "Core/Reporting.h" #include "DepalettizeShaderGLES.h" #include "GPU/GLES/TextureCacheGLES.h" -#include "ext/native/gfx/GLStateCache.h" #include "GPU/Common/DepalettizeShaderCommon.h" #ifdef _WIN32 diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index aacc8f7f31..e61f7df9d0 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -83,7 +83,6 @@ #include "GPU/Common/SplineCommon.h" #include "GPU/Common/VertexDecoderCommon.h" #include "GPU/Common/SoftwareTransformCommon.h" -#include "ext/native/gfx/GLStateCache.h" #include "GPU/GLES/FragmentTestCacheGLES.h" #include "GPU/GLES/StateMappingGLES.h" #include "GPU/GLES/TextureCacheGLES.h" @@ -585,7 +584,7 @@ rotateVBO: gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && ((hasColor && (gstate.materialupdate & 1)) || gstate.getMaterialAmbientA() == 255) && (!gstate.isLightingEnabled() || gstate.getAmbientA() == 255); } - ApplyDrawStateLate(); + ApplyDrawStateLate(false, 0); LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim); GLRInputLayout *inputLayout = SetupDecFmtForDraw(program, dec_->GetDecVtxFmt()); @@ -646,14 +645,11 @@ rotateVBO: prim, vertexCount, dec_->VertexType(), inds, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(), maxIndex, drawBuffer, numTrans, drawIndexed, ¶ms, &result); - ApplyDrawStateLate(); + ApplyDrawStateLate(result.setStencil, result.stencilValue); LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim); if (result.action == SW_DRAW_PRIMITIVES) { - if (result.setStencil) { - glstate.stencilFunc.set(GL_ALWAYS, result.stencilValue, 255); - } const int vertexSize = sizeof(transformed[0]); bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX; diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 9fd2a6080d..ea75d346e6 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -165,7 +165,7 @@ private: void DoFlush(); void ApplyDrawState(int prim); - void ApplyDrawStateLate(); + void ApplyDrawStateLate(bool setStencil, int stencilValue); void ResetShaderBlending(); GLRInputLayout *SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt); diff --git a/GPU/GLES/FragmentTestCacheGLES.h b/GPU/GLES/FragmentTestCacheGLES.h index 95eecb23cb..2b044614a3 100644 --- a/GPU/GLES/FragmentTestCacheGLES.h +++ b/GPU/GLES/FragmentTestCacheGLES.h @@ -19,7 +19,6 @@ #include #include "Common/CommonTypes.h" -#include "ext/native/gfx/GLStateCache.h" #include "GPU/GLES/TextureCacheGLES.h" #include "GPU/ge_constants.h" diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 52c2d4390f..1fbb7044a0 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -1058,6 +1058,7 @@ void FramebufferManagerGLES::DestroyAllFBOs() { void FramebufferManagerGLES::Resized() { FramebufferManagerCommon::Resized(); + render_->Resize(PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); if (UpdateSize()) { DestroyAllFBOs(); } diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index be88cda194..7887292baa 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -36,7 +36,6 @@ #include "GPU/GeDisasm.h" #include "GPU/Common/FramebufferCommon.h" -#include "ext/native/gfx/GLStateCache.h" #include "GPU/GLES/ShaderManagerGLES.h" #include "GPU/GLES/GPU_GLES.h" #include "GPU/GLES/FramebufferManagerGLES.h" @@ -160,9 +159,6 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) // Update again after init to be sure of any silly driver problems. UpdateVsyncInterval(true); - // Some of our defaults are different from hw defaults, let's assert them. - // We restore each frame anyway, but here is convenient for tests. - glstate.Restore(); textureCacheGL_->NotifyConfigChanged(); // Load shader cache. @@ -431,14 +427,6 @@ void GPU_GLES::Reinitialize() { } void GPU_GLES::InitClear() { - bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE; - if (useNonBufferedRendering) { - glstate.depthWrite.set(GL_TRUE); - glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glClearColor(0,0,0,1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - } - glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); } void GPU_GLES::BeginHostFrame() { @@ -497,7 +485,6 @@ void GPU_GLES::UpdateCmdInfo() { } void GPU_GLES::ReapplyGfxState() { - glstate.Restore(); GPUCommon::ReapplyGfxState(); } @@ -557,9 +544,6 @@ void GPU_GLES::CopyDisplayToOutput() { shaderManagerGL_->DirtyLastShader(); - glstate.depthWrite.set(GL_TRUE); - glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - framebufferManagerGL_->CopyDisplayToOutput(); framebufferManagerGL_->EndFrame(); @@ -768,8 +752,6 @@ void GPU_GLES::ClearShaderCache() { void GPU_GLES::CleanupBeforeUI() { // Clear any enabled vertex arrays. shaderManagerGL_->DirtyLastShader(); - glstate.arrayBuffer.bind(0); - glstate.elementArrayBuffer.bind(0); } void GPU_GLES::DoState(PointerWrap &p) { diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 08b9072feb..22d21f50d6 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -26,6 +26,7 @@ #include "base/logging.h" #include "base/timeutil.h" #include "gfx/gl_debug_log.h" +#include "gfx_es2/gpu_features.h" #include "thin3d/GLRenderManager.h" #include "i18n/i18n.h" #include "math/math_util.h" @@ -39,7 +40,6 @@ #include "GPU/Math3D.h" #include "GPU/GPUState.h" #include "GPU/ge_constants.h" -#include "ext/native/gfx/GLStateCache.h" #include "GPU/GLES/ShaderManagerGLES.h" #include "GPU/GLES/DrawEngineGLES.h" #include "FramebufferManagerGLES.h" diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index 54acebcb1c..bb5af37045 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -32,7 +32,6 @@ #include "Core/Config.h" #include "Core/Reporting.h" #include "GPU/GLES/GPU_GLES.h" -#include "ext/native/gfx/GLStateCache.h" #include "GPU/GLES/ShaderManagerGLES.h" #include "GPU/GLES/TextureCacheGLES.h" #include "GPU/GLES/FramebufferManagerGLES.h" @@ -169,12 +168,6 @@ void DrawEngineGLES::ApplyDrawState(int prim) { bool colorMask = gstate.isClearModeColorMask(); bool alphaMask = gstate.isClearModeAlphaMask(); renderManager->SetNoBlendAndMask((colorMask ? 7 : 0) | (alphaMask ? 8 : 0)); -#ifndef USING_GLES2 - if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { - // Logic Ops - glstate.colorLogicOp.disable(); - } -#endif } else { // Do the large chunks of state conversion. We might be able to hide these two behind a dirty-flag each, // to avoid recomputing heavy stuff unnecessarily every draw call. @@ -280,7 +273,8 @@ void DrawEngineGLES::ApplyDrawState(int prim) { if (gstate.isClearModeDepthMask()) { framebufferManager_->SetDepthUpdated(); } - renderManager->SetStencil(gstate.isClearModeAlphaMask() && enableStencilTest, GL_ALWAYS, GL_REPLACE, GL_REPLACE, GL_REPLACE, 0xFF, 0xFF, 0xFF); + renderManager->SetStencilFunc(gstate.isClearModeAlphaMask() && enableStencilTest, GL_ALWAYS, 0xFF, 0xFF); + renderManager->SetStencilOp(0xFF, GL_REPLACE, GL_REPLACE, GL_REPLACE); renderManager->SetDepth(true, gstate.isClearModeDepthMask() ? true : false, GL_ALWAYS); } else { // Depth Test @@ -293,9 +287,8 @@ void DrawEngineGLES::ApplyDrawState(int prim) { ConvertStencilFuncState(stencilState); // Stencil Test if (stencilState.enabled) { - renderManager->SetStencil(stencilState.enabled, compareOps[stencilState.testFunc], - stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass], - stencilState.writeMask, stencilState.testMask, stencilState.testRef); + renderManager->SetStencilFunc(stencilState.enabled, compareOps[stencilState.testFunc], stencilState.testRef, stencilState.testMask); + renderManager->SetStencilOp(stencilState.writeMask, stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass]); } else { renderManager->SetStencilDisabled(); } @@ -332,7 +325,11 @@ void DrawEngineGLES::ApplyDrawState(int prim) { } } -void DrawEngineGLES::ApplyDrawStateLate() { +void DrawEngineGLES::ApplyDrawStateLate(bool setStencil, int stencilValue) { + if (setStencil) { + render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, stencilValue, 255); + } + // 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()) { diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 15da119330..1cd17c8c38 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -17,7 +17,6 @@ #include "gfx_es2/glsl_program.h" #include "Core/Reporting.h" -#include "ext/native/gfx/GLStateCache.h" #include "GPU/Common/StencilCommon.h" #include "GPU/GLES/FramebufferManagerGLES.h" #include "GPU/GLES/ShaderManagerGLES.h" @@ -111,12 +110,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe } // Let's not bother with the shader if it's just zero. - glstate.scissorTest.disable(); - glstate.colorMask.set(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - glClearColor(0, 0, 0, 0); - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - + render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE); return true; } @@ -150,8 +144,6 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe DisableState(); render_->SetNoBlendAndMask(0x8); - glstate.stencilTest.enable(); - glstate.stencilOp.set(GL_REPLACE, GL_REPLACE, GL_REPLACE); bool useBlit = gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT); @@ -178,7 +170,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe textureCacheGL_->ForgetLastTexture(); render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT); - render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, 0xFF, 0xFF, 0xFF); + render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF); for (int i = 1; i < values; i += i) { if (!(usedBits & i)) { @@ -186,18 +178,17 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe continue; } if (dstBuffer->format == GE_FORMAT_4444) { - render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, (i << 4) | i, 0xFF, 0xFF); + render_->SetStencilOp((i << 4) | i, GL_KEEP, GL_KEEP, GL_KEEP); render_->SetUniformF1(&u_stencilValue, i * (16.0f / 255.0f)); } else if (dstBuffer->format == GE_FORMAT_5551) { - glstate.stencilMask.set(0xFF); + render_->SetStencilOp(0xFF, GL_KEEP, GL_KEEP, GL_KEEP); render_->SetUniformF1(&u_stencilValue, i * (128.0f / 255.0f)); } else { - render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, i, 0xFF, 0xFF); + render_->SetStencilOp(i, GL_KEEP, GL_KEEP, GL_KEEP); render_->SetUniformF1(&u_stencilValue, i * (1.0f / 255.0f)); } DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST); } - render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, 0xFF, 0xFF, 0xFF); if (useBlit) { draw_->BlitFramebuffer(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, Draw::FB_STENCIL_BIT, Draw::FB_BLIT_NEAREST); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 307b208342..9747dad92f 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -32,7 +32,6 @@ #include "Core/Reporting.h" #include "GPU/ge_constants.h" #include "GPU/GPUState.h" -#include "ext/native/gfx/GLStateCache.h" #include "GPU/GLES/TextureCacheGLES.h" #include "GPU/GLES/FramebufferManagerGLES.h" #include "GPU/GLES/FragmentShaderGeneratorGLES.h" @@ -523,6 +522,10 @@ GLenum ToGLESFormat(ReplacedTextureFormat fmt) { void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImages) { entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK; + // Never replace images in-place - there's no such thing, drivers have to fake it anyway, at least if + // the image has been in use within the last frame or two. + replaceImages = false; + // For the estimate, we assume cluts always point to 8888 for simplicity. cacheSizeEstimate_ += EstimateTexMemoryUsage(entry); diff --git a/Qt/Debugger/debugger_memorytex.cpp b/Qt/Debugger/debugger_memorytex.cpp index 51af9915c5..f077daaaf7 100644 --- a/Qt/Debugger/debugger_memorytex.cpp +++ b/Qt/Debugger/debugger_memorytex.cpp @@ -1,5 +1,4 @@ #include "debugger_memorytex.h" -#include "gfx/GLStateCache.h" #include "gfx/gl_common.h" #include "ui_debugger_memorytex.h" #include "Core/MemMap.h" diff --git a/ext/native/Android.mk b/ext/native/Android.mk index 5656512d81..fd0e69181f 100644 --- a/ext/native/Android.mk +++ b/ext/native/Android.mk @@ -75,7 +75,6 @@ LOCAL_SRC_FILES :=\ gfx_es2/draw_buffer.cpp.arm \ gfx_es2/draw_text.cpp.arm \ gfx_es2/draw_text_android.cpp.arm \ - gfx/GLStateCache.cpp.arm \ gfx/gl_debug_log.cpp \ gfx/texture_atlas.cpp \ image/zim_load.cpp \ diff --git a/ext/native/gfx/GLStateCache.cpp b/ext/native/gfx/GLStateCache.cpp deleted file mode 100644 index b4edffc1aa..0000000000 --- a/ext/native/gfx/GLStateCache.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include - -#include "base/logging.h" - -#include "gfx/GLStateCache.h" - -OpenGLState glstate; - -int OpenGLState::state_count = 0; - -void OpenGLState::Restore() { - int count = 0; - - blend.restore(); count++; - blendEquationSeparate.restore(); count++; - blendFuncSeparate.restore(); count++; - blendColor.restore(); count++; - - scissorTest.restore(); count++; - scissorRect.restore(); count++; - - cullFace.restore(); count++; - cullFaceMode.restore(); count++; - frontFace.restore(); count++; - - depthTest.restore(); count++; - depthRange.restore(); count++; - depthFunc.restore(); count++; - depthWrite.restore(); count++; - - colorMask.restore(); count++; - viewport.restore(); count++; - - stencilTest.restore(); count++; - stencilOp.restore(); count++; - stencilFunc.restore(); count++; - stencilMask.restore(); count++; - - dither.restore(); count++; - -#if !defined(USING_GLES2) - colorLogicOp.restore(); count++; - logicOp.restore(); count++; -#endif - - arrayBuffer.restore(); count++; - elementArrayBuffer.restore(); count++; - - if (count != state_count) { - FLOG("OpenGLState::Restore is missing some states"); - } -} diff --git a/ext/native/gfx/GLStateCache.h b/ext/native/gfx/GLStateCache.h deleted file mode 100644 index e46133709f..0000000000 --- a/ext/native/gfx/GLStateCache.h +++ /dev/null @@ -1,283 +0,0 @@ -#pragma once - -#include -#include // for memcmp - -#include "gfx/gl_common.h" -#include "gfx_es2/gpu_features.h" - -// OpenGL state cache. -// Probably only really worth it in rendering cores on weak mobile hardware. -class OpenGLState { -private: - template - class BoolState { - private: - bool v; - public: - BoolState() : v(init) { - OpenGLState::state_count++; - } - - inline void set(bool value) { - if (value != v) { - v = value; - restore(); - } - } - inline void force(bool value) { - bool old = v; - set(value); - v = old; - } - inline void enable() { - set(true); - } - inline void disable() { - set(false); - } - operator bool() const { - return isset(); - } - inline bool isset() { - return v; - } - void restore() { - if (v) - glEnable(cap); - else - glDisable(cap); - } - }; - -#define STATE1(func, p1type, p1def) \ - class SavedState1_##func { \ - p1type p1; \ - public: \ - SavedState1_##func() : p1(p1def) { \ - OpenGLState::state_count++; \ - } \ - void set(p1type newp1) { \ - if (newp1 != p1) { \ - p1 = newp1; \ - restore(); \ - } \ - } \ - void force(p1type newp1) { \ - p1type old = p1; \ - set(newp1); \ - p1 = old; \ - } \ - inline void restore() { \ - func(p1); \ - } \ - } - -#define STATE2(func, p1type, p2type, p1def, p2def) \ - class SavedState2_##func { \ - p1type p1; \ - p2type p2; \ - public: \ - SavedState2_##func() : p1(p1def), p2(p2def) { \ - OpenGLState::state_count++; \ - } \ - inline void set(p1type newp1, p2type newp2) { \ - if (newp1 != p1 || newp2 != p2) { \ - p1 = newp1; \ - p2 = newp2; \ - restore(); \ - } \ - } \ - void force(p1type newp1, p2type newp2) { \ - p1type old1 = p1; \ - p2type old2 = p2; \ - set(newp1, newp2); \ - p1 = old1; \ - p2 = old2; \ - } \ - inline void restore() { \ - func(p1, p2); \ - } \ - } - -#define STATE3(func, p1type, p2type, p3type, p1def, p2def, p3def) \ - class SavedState3_##func { \ - p1type p1; \ - p2type p2; \ - p3type p3; \ - public: \ - SavedState3_##func() : p1(p1def), p2(p2def), p3(p3def) { \ - OpenGLState::state_count++; \ - } \ - inline void set(p1type newp1, p2type newp2, p3type newp3) { \ - if (newp1 != p1 || newp2 != p2 || newp3 != p3) { \ - p1 = newp1; \ - p2 = newp2; \ - p3 = newp3; \ - restore(); \ - } \ - } \ - void force(p1type newp1, p2type newp2, p3type newp3) { \ - p1type old1 = p1; \ - p2type old2 = p2; \ - p3type old3 = p3; \ - set(newp1, newp2, newp3); \ - p1 = old1; \ - p2 = old2; \ - p3 = old3; \ - } \ - inline void restore() { \ - func(p1, p2, p3); \ - } \ - } - - #define STATE4(func, p1type, p2type, p3type, p4type, p1def, p2def, p3def, p4def) \ - class SavedState4_##func { \ - p1type p1; \ - p2type p2; \ - p3type p3; \ - p4type p4; \ - public: \ - SavedState4_##func() : p1(p1def), p2(p2def), p3(p3def), p4(p4def) { \ - OpenGLState::state_count++; \ - } \ - inline void set(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \ - if (newp1 != p1 || newp2 != p2 || newp3 != p3 || newp4 != p4) { \ - p1 = newp1; \ - p2 = newp2; \ - p3 = newp3; \ - p4 = newp4; \ - restore(); \ - } \ - } \ - void force(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \ - p1type old1 = p1; \ - p2type old2 = p2; \ - p3type old3 = p3; \ - p4type old4 = p4; \ - set(newp1, newp2, newp3, newp4); \ - p1 = old1; \ - p2 = old2; \ - p3 = old3; \ - p4 = old4; \ - } \ - inline void restore() { \ - func(p1, p2, p3, p4); \ - } \ - } - -#define STATEFLOAT4(func, def) \ - class SavedState4_##func { \ - float p[4]; \ - public: \ - SavedState4_##func() { \ - for (int i = 0; i < 4; i++) {p[i] = def;} \ - OpenGLState::state_count++; \ - } \ - inline void set(const float v[4]) { \ - if (memcmp(p, v, sizeof(float) * 4)) { \ - memcpy(p, v, sizeof(float) * 4); \ - restore(); \ - } \ - } \ - void force(const float v[4]) { \ - float old[4]; \ - memcpy(old, p, sizeof(float) * 4); \ - set(v); \ - memcpy(p, old, sizeof(float) * 4); \ - } \ - inline void restore() { \ - func(p[0], p[1], p[2], p[3]); \ - } \ - } - -#define STATEBIND(func, target) \ - class SavedBind_##func_##target { \ - GLuint val_; \ - public: \ - SavedBind_##func_##target() { \ - val_ = 0; \ - OpenGLState::state_count++; \ - } \ - inline void bind(GLuint val) { \ - if (val_ != val) { \ - val_ = val; \ - restore(); \ - } \ - } \ - inline void force(GLuint val) { \ - GLuint old = val_; \ - bind(val); \ - val_ = old; \ - } \ - inline void unbind() { \ - bind(0); \ - } \ - inline void restore() { \ - func(target, val_); \ - } \ - } - -public: - static int state_count; - OpenGLState() {} - void Restore(); - - // When adding a state here, don't forget to add it to OpenGLState::Restore() too - - // Blending - BoolState blend; - STATE4(glBlendFuncSeparate, GLenum, GLenum, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFuncSeparate; - - // On OpenGL ES, using minmax blend requires glBlendEquationEXT (in theory at least but I don't think it's true in practice) - STATE2(glBlendEquationSeparate, GLenum, GLenum, GL_FUNC_ADD, GL_FUNC_ADD) blendEquationSeparate; - STATEFLOAT4(glBlendColor, 1.0f) blendColor; - - // Logic Ops. Not available on OpenGL ES at all. -#if !defined(USING_GLES2) - BoolState colorLogicOp; - STATE1(glLogicOp, GLenum, GL_COPY) logicOp; -#endif - - // Dither - BoolState dither; - - // Cull Face - BoolState cullFace; - STATE1(glCullFace, GLenum, GL_FRONT) cullFaceMode; - STATE1(glFrontFace, GLenum, GL_CCW) frontFace; - - // Depth Test - BoolState depthTest; -#if defined(USING_GLES2) - STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; -#else - STATE2(glDepthRange, double, double, 0.0, 1.0) depthRange; -#endif - STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; - STATE1(glDepthMask, GLboolean, GL_TRUE) depthWrite; - - // Color Mask - STATE4(glColorMask, bool, bool, bool, bool, true, true, true, true) colorMask; - - // Viewport - STATE4(glViewport, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) viewport; - - // Scissor Test - BoolState scissorTest; - STATE4(glScissor, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) scissorRect; - - // Stencil Test - BoolState stencilTest; - STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp; - STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc; - STATE1(glStencilMask, GLuint, 0xFF) stencilMask; - - STATEBIND(glBindBuffer, GL_ARRAY_BUFFER) arrayBuffer; - STATEBIND(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER) elementArrayBuffer; -}; - -#undef STATE1 -#undef STATE2 - -extern OpenGLState glstate; diff --git a/ext/native/native.vcxproj b/ext/native/native.vcxproj index 3f520beb66..a9929e396a 100644 --- a/ext/native/native.vcxproj +++ b/ext/native/native.vcxproj @@ -232,7 +232,6 @@ - @@ -693,7 +692,6 @@ - diff --git a/ext/native/native.vcxproj.filters b/ext/native/native.vcxproj.filters index d452261752..7336d62265 100644 --- a/ext/native/native.vcxproj.filters +++ b/ext/native/native.vcxproj.filters @@ -302,9 +302,6 @@ gfx - - gfx - thin3d @@ -775,9 +772,6 @@ gfx - - gfx - thin3d @@ -883,4 +877,4 @@ {06c6305a-a646-485b-85b9-645a24dd6553} - + \ No newline at end of file diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 42b25e040f..cf886b25ef 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -279,13 +279,24 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glBlendColor(c.blendColor.color[0], c.blendColor.color[1], c.blendColor.color[2], c.blendColor.color[3]); break; case GLRRenderCommand::VIEWPORT: + { + float y = c.viewport.vp.y; + if (!curFramebuffer_) + y = curFBHeight_ - y - c.viewport.vp.h; + // TODO: Support FP viewports through glViewportArrays - glViewport((GLint)c.viewport.vp.x, (GLint)c.viewport.vp.y, (GLsizei)c.viewport.vp.w, (GLsizei)c.viewport.vp.h); + glViewport((GLint)c.viewport.vp.x, (GLint)y, (GLsizei)c.viewport.vp.w, (GLsizei)c.viewport.vp.h); glDepthRange(c.viewport.vp.minZ, c.viewport.vp.maxZ); break; + } case GLRRenderCommand::SCISSOR: - glScissor(c.scissor.rc.x, c.scissor.rc.y, c.scissor.rc.w, c.scissor.rc.h); + { + int y = c.scissor.rc.y; + if (!curFramebuffer_) + y = curFBHeight_ - y - c.scissor.rc.h; + glScissor(c.scissor.rc.x, y, c.scissor.rc.w, c.scissor.rc.h); break; + } case GLRRenderCommand::UNIFORM4F: { int loc = c.uniform4.loc ? *c.uniform4.loc : -1; @@ -345,24 +356,30 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } break; } - case GLRRenderCommand::STENCIL: - if (c.stencil.enabled) { + case GLRRenderCommand::STENCILFUNC: + if (c.stencilFunc.enabled) { glEnable(GL_STENCIL_TEST); - glStencilFunc(c.stencil.func, c.stencil.ref, c.stencil.compareMask); - glStencilOp(c.stencil.sFail, c.stencil.zFail, c.stencil.pass); - glStencilMask(c.stencil.writeMask); } else { glDisable(GL_STENCIL_TEST); } + glStencilFunc(c.stencilFunc.func, c.stencilFunc.ref, c.stencilFunc.compareMask); + break; + case GLRRenderCommand::STENCILOP: + glStencilOp(c.stencilOp.sFail, c.stencilOp.zFail, c.stencilOp.pass); + glStencilMask(c.stencilOp.writeMask); break; case GLRRenderCommand::BINDTEXTURE: { - GLint target = c.texture.slot; - if (target != activeTexture) { - glActiveTexture(GL_TEXTURE0 + target); - activeTexture = target; + GLint slot = c.texture.slot; + if (slot != activeTexture) { + glActiveTexture(GL_TEXTURE0 + slot); + activeTexture = slot; + } + if (c.texture.texture) { + glBindTexture(c.texture.texture->target, c.texture.texture->texture); + } else { + glBindTexture(GL_TEXTURE_2D, 0); // ? } - glBindTexture(c.texture.texture->target, c.texture.texture->texture); break; } case GLRRenderCommand::BINDPROGRAM: @@ -518,7 +535,13 @@ void GLQueueRunner::PerformReadbackImage(const GLRStep &pass) { } void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) { - + if (pass.render.framebuffer) { + curFBWidth_ = pass.render.framebuffer->width; + curFBHeight_ = pass.render.framebuffer->height; + } else { + curFBWidth_ = targetWidth_; + curFBHeight_ = targetHeight_; + } } void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index f6ddf68ef9..f26d995d5e 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -28,7 +28,8 @@ class GLRInputLayout; enum class GLRRenderCommand : uint8_t { DEPTH, - STENCIL, + STENCILFUNC, + STENCILOP, BLEND, BLENDCOLOR, UNIFORM4I, @@ -77,13 +78,15 @@ struct GLRRenderData { struct { GLboolean enabled; GLenum func; - uint8_t writeMask; - uint8_t compareMask; uint8_t ref; + uint8_t compareMask; + } stencilFunc; + struct { GLenum sFail; GLenum zFail; GLenum pass; - } stencil; + uint8_t writeMask; + } stencilOp; // also write mask struct { GLenum mode; // primitive GLint buffer; @@ -299,6 +302,10 @@ public: void CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels); + void Resize(int width, int height) { + targetWidth_ = width; + targetHeight_ = height; + } private: void PerformBindFramebufferAsRenderTarget(const GLRStep &pass); void PerformRenderPass(const GLRStep &pass); @@ -318,8 +325,10 @@ private: GLuint globalVAO_; GLint curFramebuffer_ = 0; - int curFBWidth_; - int curFBHeight_; + int curFBWidth_ = 0; + int curFBHeight_ = 0; + int targetWidth_ = 0; + int targetHeight_ = 0; // Readback buffer. Currently we only support synchronous readback, so we only really need one. // We size it generously. diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 19c82ee043..1e20c17827 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -456,25 +456,31 @@ public: curRenderStep_->commands.push_back(data); } - void SetStencil(bool enabled, GLenum func, GLenum sFail, GLenum zFail, GLenum pass, uint8_t writeMask, uint8_t compareMask, uint8_t refValue) { + void SetStencilFunc(bool enabled, GLenum func, uint8_t refValue, uint8_t compareMask) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData data{ GLRRenderCommand::STENCIL }; - data.stencil.enabled = enabled; - data.stencil.func = func; - data.stencil.sFail = sFail; - data.stencil.zFail = zFail; - data.stencil.pass = pass; - data.stencil.writeMask = writeMask; - data.stencil.compareMask = compareMask; - data.stencil.ref = refValue; + GLRRenderData data{ GLRRenderCommand::STENCILFUNC }; + data.stencilFunc.enabled = enabled; + data.stencilFunc.func = func; + data.stencilFunc.ref = refValue; + data.stencilFunc.compareMask = compareMask; + curRenderStep_->commands.push_back(data); + } + + void SetStencilOp(uint8_t writeMask, GLenum sFail, GLenum zFail, GLenum pass) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::STENCILOP }; + data.stencilOp.writeMask = writeMask; + data.stencilOp.sFail = sFail; + data.stencilOp.zFail = zFail; + data.stencilOp.pass = pass; curRenderStep_->commands.push_back(data); } void SetStencilDisabled() { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data; - data.cmd = GLRRenderCommand::STENCIL; - data.stencil.enabled = false; + data.cmd = GLRRenderCommand::STENCILFUNC; + data.stencilFunc.enabled = false; curRenderStep_->commands.push_back(data); } @@ -546,6 +552,12 @@ public: return curFrame_; } + void Resize(int width, int height) { + targetWidth_ = width; + targetHeight_ = height; + queueRunner_.Resize(width, height); + } + private: void BeginSubmitFrame(int frame); void EndSubmitFrame(int frame); @@ -601,6 +613,9 @@ private: bool useThread_ = false; int curFrame_ = 0; + + int targetWidth_ = 0; + int targetHeight_ = 0; }; diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 6bbc0d50e8..3427773c24 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -633,7 +633,7 @@ public: virtual void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) = 0; // Necessary to correctly flip scissor rectangles etc for OpenGL. - void SetTargetSize(int w, int h) { + virtual void SetTargetSize(int w, int h) { targetWidth_ = w; targetHeight_ = h; } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 751e839e22..cc0fb5299c 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -11,7 +11,6 @@ #include "thin3d/thin3d.h" #include "gfx/gl_common.h" #include "gfx/gl_debug_log.h" -#include "gfx/GLStateCache.h" #include "gfx_es2/gpu_features.h" #include "thin3d/GLRenderManager.h" @@ -207,7 +206,8 @@ public: void Apply(GLRenderManager *render) { render->SetDepth(depthTestEnabled, depthWriteEnabled, depthComp); - render->SetStencil(stencilEnabled, stencilCompareOp, stencilFail, stencilZFail, stencilPass, stencilWriteMask, stencilCompareMask, stencilReference); + render->SetStencilFunc(stencilEnabled, stencilCompareOp, stencilReference, stencilCompareMask); + render->SetStencilOp(stencilWriteMask, stencilFail, stencilZFail, stencilPass); } }; @@ -345,6 +345,11 @@ public: OpenGLContext(); virtual ~OpenGLContext(); + void SetTargetSize(int w, int h) override { + DrawContext::SetTargetSize(w, h); + renderManager_.Resize(w, h); + } + const DeviceCaps &GetDeviceCaps() const override { return caps_; } From 7e3e6529630da3ad2ff562702f8aedf06302f6eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 12 Dec 2017 15:32:15 +0100 Subject: [PATCH 014/291] Fix more gl-render-manager problems --- GPU/GLES/FragmentTestCacheGLES.cpp | 6 +++--- GPU/GLES/FragmentTestCacheGLES.h | 2 +- GPU/GLES/FramebufferManagerGLES.cpp | 7 +++++-- GPU/GLES/StateMappingGLES.cpp | 2 +- ext/native/thin3d/GLQueueRunner.cpp | 6 +++++- ext/native/thin3d/GLRenderManager.h | 16 +++++++++++----- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/GPU/GLES/FragmentTestCacheGLES.cpp b/GPU/GLES/FragmentTestCacheGLES.cpp index 0228f3896e..4098186d20 100644 --- a/GPU/GLES/FragmentTestCacheGLES.cpp +++ b/GPU/GLES/FragmentTestCacheGLES.cpp @@ -37,7 +37,7 @@ FragmentTestCacheGLES::~FragmentTestCacheGLES() { delete [] scratchpad_; } -void FragmentTestCacheGLES::BindTestTexture(GLenum unit) { +void FragmentTestCacheGLES::BindTestTexture(int slot) { if (!g_Config.bFragmentTestCache) { return; } @@ -58,7 +58,7 @@ void FragmentTestCacheGLES::BindTestTexture(GLenum unit) { // Already bound, hurray. return; } - render_->BindTexture(unit, tex); + render_->BindTexture(slot, tex); lastTexture_ = tex; return; } @@ -78,7 +78,7 @@ void FragmentTestCacheGLES::BindTestTexture(GLenum unit) { GLRTexture *tex = CreateTestTexture(funcs, refs, masks, valid); lastTexture_ = tex; - render_->BindTexture(unit, tex); + render_->BindTexture(slot, tex); FragmentTestTexture item; item.lastFrame = gpuStats.numFlips; item.texture = tex; diff --git a/GPU/GLES/FragmentTestCacheGLES.h b/GPU/GLES/FragmentTestCacheGLES.h index 2b044614a3..9b6ac1d1be 100644 --- a/GPU/GLES/FragmentTestCacheGLES.h +++ b/GPU/GLES/FragmentTestCacheGLES.h @@ -65,7 +65,7 @@ public: textureCache_ = tc; } - void BindTestTexture(GLenum unit); + void BindTestTexture(int slot); void Clear(bool deleteThem = true); void Decimate(); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 1fbb7044a0..96e8ef5d7f 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -103,13 +103,16 @@ void FramebufferManagerGLES::CompileDraw2DProgram() { vs_code = ApplyGLSLPrelude(basic_vs, GL_VERTEX_SHADER); fs_code = ApplyGLSLPrelude(tex_fs, GL_FRAGMENT_SHADER); std::vector shaders; - GLRShader *vs = render_->CreateShader(GL_VERTEX_SHADER, vs_code); - GLRShader *fs = render_->CreateShader(GL_FRAGMENT_SHADER, fs_code); + shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vs_code)); + shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fs_code)); + std::vector queries; queries.push_back({ &u_draw2d_tex, "u_tex" }); std::vector initializers; initializers.push_back({ &u_draw2d_tex, 0 }); draw2dprogram_ = render_->CreateProgram(shaders, {}, queries, initializers, false); + for (auto shader : shaders) + render_->DeleteShader(shader); CompilePostShader(); } } diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index bb5af37045..11b7e79576 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -347,7 +347,7 @@ void DrawEngineGLES::ApplyDrawStateLate(bool setStencil, int stencilValue) { // Apply last, once we know the alpha params of the texture. if (gstate.isAlphaTestEnabled() || gstate.isColorTestEnabled()) { - fragmentTestCache_->BindTestTexture(GL_TEXTURE2); + fragmentTestCache_->BindTestTexture(2); } } } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index cf886b25ef..0f738f2ded 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -53,7 +53,9 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { { GLRProgram *program = step.create_program.program; program->program = glCreateProgram(); + _assert_msg_(G3D, step.create_program.num_shaders > 0, "Can't create a program with zero shaders"); for (int i = 0; i < step.create_program.num_shaders; i++) { + _dbg_assert_msg_(G3D, step.create_program.shaders[i]->shader, "Can't create a program with a null shader"); glAttachShader(program->program, step.create_program.shaders[i]->shader); } @@ -141,7 +143,9 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { glDeleteShader(shader); shader = 0; ILOG("%s Shader compile error:\n%s", step.create_shader.stage == GL_FRAGMENT_SHADER ? "Fragment" : "Vertex", infoLog); + step.create_shader.shader->valid = false; } + step.create_shader.shader->valid = true; break; } case GLRInitStepType::CREATE_INPUT_LAYOUT: @@ -359,10 +363,10 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { case GLRRenderCommand::STENCILFUNC: if (c.stencilFunc.enabled) { glEnable(GL_STENCIL_TEST); + glStencilFunc(c.stencilFunc.func, c.stencilFunc.ref, c.stencilFunc.compareMask); } else { glDisable(GL_STENCIL_TEST); } - glStencilFunc(c.stencilFunc.func, c.stencilFunc.ref, c.stencilFunc.compareMask); break; case GLRRenderCommand::STENCILOP: glStencilOp(c.stencilOp.sFail, c.stencilOp.zFail, c.stencilOp.pass); diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 1e20c17827..b014302f52 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -52,6 +52,7 @@ public: } } GLuint shader = 0; + bool valid = false; }; class GLRProgram { @@ -116,7 +117,7 @@ public: class GLRBuffer { public: - GLRBuffer(GLuint target) : target_(target) {} + GLRBuffer(GLuint target, size_t size) : target_(target), size_((int)size) {} ~GLRBuffer() { if (buffer) { glDeleteBuffers(1, &buffer); @@ -124,6 +125,7 @@ public: } GLuint buffer = 0; GLuint target_; + int size_; private: }; @@ -192,7 +194,7 @@ public: GLRBuffer *CreateBuffer(GLuint target, size_t size, GLuint usage) { GLRInitStep step{ GLRInitStepType::CREATE_BUFFER }; - step.create_buffer.buffer = new GLRBuffer(target); + step.create_buffer.buffer = new GLRBuffer(target, size); step.create_buffer.size = (int)size; step.create_buffer.usage = usage; initSteps_.push_back(step); @@ -227,6 +229,7 @@ public: step.create_program.program->semantics_ = semantics; step.create_program.program->queries_ = queries; step.create_program.program->initialize_ = initalizers; + _assert_msg_(G3D, shaders.size() > 0, "Can't create a program with zero shaders"); for (int i = 0; i < shaders.size(); i++) { step.create_program.shaders[i] = shaders[i]; } @@ -283,6 +286,8 @@ public: // TODO: Maybe should be a render command instead of an init command? When possible it's better as // an init command, that's for sure. GLRInitStep step{ GLRInitStepType::BUFFER_SUBDATA }; + _dbg_assert_(G3D, offset >= 0); + _dbg_assert_(G3D, offset <= buffer->size_ - size); step.buffer_subdata.buffer = buffer; step.buffer_subdata.offset = offset; step.buffer_subdata.size = size; @@ -309,6 +314,7 @@ public: void BindTexture(int slot, GLRTexture *tex) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::BINDTEXTURE }; + _dbg_assert_(G3D, slot < 16); data.texture.slot = slot; data.texture.texture = tex; curRenderStep_->commands.push_back(data); @@ -662,12 +668,12 @@ public: // This will later allow for handling overflow correctly. size_t Allocate(size_t numBytes, GLRBuffer **vkbuf) { size_t out = offset_; - offset_ += (numBytes + 3) & ~3; // Round up to 4 bytes. - - if (offset_ >= size_) { + if (offset_ + ((numBytes + 3) & ~3) >= size_) { NextBuffer(numBytes); out = offset_; offset_ += (numBytes + 3) & ~3; + } else { + offset_ += (numBytes + 3) & ~3; // Round up to 4 bytes. } *vkbuf = buffers_[buf_].buffer; return out; From 062608ad7822ff690d706ddac1bc01b6b4beb4cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 13 Dec 2017 01:05:33 +0100 Subject: [PATCH 015/291] Start moving the framebuffer stuff over to the render manager --- GPU/GLES/TextureCacheGLES.cpp | 51 +--- android/jni/app-android.cpp | 7 +- ext/native/thin3d/GLQueueRunner.cpp | 359 +++++++++++++++++++++- ext/native/thin3d/GLQueueRunner.h | 18 ++ ext/native/thin3d/GLRenderManager.cpp | 18 +- ext/native/thin3d/GLRenderManager.h | 46 ++- ext/native/thin3d/thin3d_gl.cpp | 419 +------------------------- 7 files changed, 443 insertions(+), 475 deletions(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 9747dad92f..ddbc29b4bf 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -121,35 +121,34 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, maxLevel, entry.addr, mode); if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) { + float minLod = 0.0f; + float maxLod = 0.0f; if (maxLevel != 0) { // TODO: What about a swap of autoMip mode? if (force || entry.lodBias != lodBias) { if (mode == GE_TEXLEVEL_MODE_AUTO) { -#ifndef USING_GLES2 - // Sigh, LOD_BIAS is not even in ES 3.0.. but we could do it in the shader via texture()... - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, lodBias); -#endif - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (float)maxLevel); + minLod = 0.0f; + maxLod = (float)maxLevel; } else if (mode == GE_TEXLEVEL_MODE_CONST) { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, std::max(0.0f, std::min((float)maxLevel, lodBias))); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, std::max(0.0f, std::min((float)maxLevel, lodBias))); + minLod = std::max(0.0f, std::min((float)maxLevel, lodBias)); + maxLod = std::max(0.0f, std::min((float)maxLevel, lodBias)); } else { // mode == GE_TEXLEVEL_MODE_SLOPE) { // It's incorrect to use the slope as a bias. Instead it should be passed // into the shader directly as an explicit lod level, with the bias on top. For now, we just kill the // lodBias in this mode, working around #9772. #ifndef USING_GLES2 - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.0f); + lodBias = 0.0f; #endif - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (float)maxLevel); + minLod = 0.0f; + maxLod = (float)maxLevel; } entry.lodBias = lodBias; } } else { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0.0f); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0.0f); + minLod = 0.0f; + maxLod = 0.0f; } + render_->SetTextureLod(minLod, maxLod, lodBias); } if (force || entry.minFilt != minFilt || entry.magFilt != magFilt || entry.sClamp != sClamp || entry.tClamp != tClamp) { @@ -636,29 +635,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag // glBindTexture(GL_TEXTURE_2D, entry->textureName); lastBoundTexture = entry->textureName; - - // Disabled this due to issue #6075: https://github.com/hrydgard/ppsspp/issues/6075 - // This breaks Dangan Ronpa 2 with mipmapping enabled. Why? No idea, it shouldn't. - // glTexStorage2D probably has few benefits for us anyway. - if (false && gl_extensions.GLES3 && maxLevel > 0) { - // glTexStorage2D requires the use of sized formats. - GLenum actualFmt = replaced.Valid() ? ToGLESFormat(replaced.Format(0)) : dstFmt; - GLenum storageFmt = GL_RGBA8; - switch (actualFmt) { - case GL_UNSIGNED_BYTE: storageFmt = GL_RGBA8; break; - case GL_UNSIGNED_SHORT_5_6_5: storageFmt = GL_RGB565; break; - case GL_UNSIGNED_SHORT_4_4_4_4: storageFmt = GL_RGBA4; break; - case GL_UNSIGNED_SHORT_5_5_5_1: storageFmt = GL_RGB5_A1; break; - default: - ERROR_LOG(G3D, "Unknown dstfmt %i", (int)actualFmt); - break; - } - // TODO: This may cause bugs, since it hard-sets the texture w/h, and we might try to reuse it later with a different size. - glTexStorage2D(GL_TEXTURE_2D, maxLevel + 1, storageFmt, w * scaleFactor, h * scaleFactor); - // Make sure we don't use glTexImage2D after glTexStorage2D. - replaceImages = true; - } - + // GLES2 doesn't have support for a "Max lod" which is critical as PSP games often // don't specify mips all the way down. As a result, we either need to manually generate // the bottom few levels or rely on OpenGL's autogen mipmaps instead, which might not @@ -703,8 +680,6 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag texMaxLevel = 0; } - // TODO: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, texMaxLevel); - if (maxLevel == 0) { entry->status |= TexCacheEntry::STATUS_BAD_MIPS; } else { diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 05306c22be..48fe18013c 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -486,12 +486,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, time_update(); } else { ELOG("BAD: Ended up in nativeRender even though app has quit.%s", ""); - // Shouldn't really get here. Let's draw magenta. - // TODO: Should we have GL here? - glDepthMask(GL_TRUE); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glClearColor(1.0, 0.0, 1.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + // Shouldn't really get here. } std::lock_guard guard(frameCommandLock); diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 0f738f2ded..7c8f61d3c5 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -8,6 +8,12 @@ #define TEXCACHE_NAME_CACHE_SIZE 16 +// Workaround for Retroarch. Simply declare +// extern GLuint g_defaultFBO; +// and set is as appropriate. Can adjust the variables in ext/native/base/display.h as +// appropriate. +GLuint g_defaultFBO = 0; + void GLQueueRunner::CreateDeviceObjects() { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel_); glGenVertexArrays(1, &globalVAO_); @@ -156,7 +162,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { } case GLRInitStepType::CREATE_FRAMEBUFFER: { - // TODO + InitCreateFramebuffer(step); break; } case GLRInitStepType::TEXTURE_SUBDATA: @@ -180,6 +186,114 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { } } +void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) { + GLRFramebuffer *fbo = step.create_framebuffer.framebuffer; + +#ifndef USING_GLES2 + if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) { + fbo_ext_create(step); + } else if (!gl_extensions.ARB_framebuffer_object) { + return; + } + // If GLES2, we have basic FBO support and can just proceed. +#endif + CHECK_GL_ERROR_IF_DEBUG(); + + // Color texture is same everywhere + glGenFramebuffers(1, &fbo->handle); + glGenTextures(1, &fbo->color_texture); + + // Create the surfaces. + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + 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_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + 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_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + if (gl_extensions.IsGLES) { + if (gl_extensions.OES_packed_depth_stencil) { + ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", fbo->width, fbo->height); + // Standard method + fbo->stencil_buffer = 0; + fbo->z_buffer = 0; + // 24-bit Z, 8-bit stencil combined + glGenRenderbuffers(1, &fbo->z_stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, fbo->width, fbo->height); + + // Bind it all together + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + } else { + ILOG("Creating %i x %i FBO using separate stencil", fbo->width, fbo->height); + // TEGRA + fbo->z_stencil_buffer = 0; + // 16/24-bit Z, separate 8-bit stencil + glGenRenderbuffers(1, &fbo->z_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer); + // Don't forget to make sure fbo_standard_z_depth() matches. + glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, fbo->width, fbo->height); + + // 8-bit stencil buffer + glGenRenderbuffers(1, &fbo->stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, fbo->width, fbo->height); + + // Bind it all together + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer); + } + } else { + fbo->stencil_buffer = 0; + fbo->z_buffer = 0; + // 24-bit Z, 8-bit stencil + glGenRenderbuffers(1, &fbo->z_stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, fbo->width, fbo->height); + + // Bind it all together + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + } + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + switch (status) { + case GL_FRAMEBUFFER_COMPLETE: + // ILOG("Framebuffer verified complete."); + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); + break; + default: + FLOG("Other framebuffer error: %i", status); + break; + } + + // Unbind state we don't need + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + CHECK_GL_ERROR_IF_DEBUG(); + + currentDrawHandle_ = fbo->handle; + currentReadHandle_ = fbo->handle; +} + void GLQueueRunner::RunSteps(const std::vector &steps) { for (int i = 0; i < steps.size(); i++) { const GLRStep &step = *steps[i]; @@ -213,6 +327,25 @@ void GLQueueRunner::LogSteps(const std::vector &steps) { void GLQueueRunner::PerformBlit(const GLRStep &step) { + /* + // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing + // in ES 2.0 that actually separate them anyway of course, so doesn't matter. + fbo_bind_fb_target(false, dst->handle); + fbo_bind_fb_target(true, src->handle); + if (gl_extensions.GLES3 || gl_extensions.ARB_framebuffer_object) { + glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, aspect, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST); + CHECK_GL_ERROR_IF_DEBUG(); + #if defined(USING_GLES2) && defined(__ANDROID__) // We only support this extension on Android, it's not even available on PC. + return true; + } else if (gl_extensions.NV_framebuffer_blit) { + glBlitFramebufferNV(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, aspect, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST); + CHECK_GL_ERROR_IF_DEBUG(); + #endif // defined(USING_GLES2) && defined(__ANDROID__) + return true; + } else { + return false; + }*/ + } void GLQueueRunner::PerformRenderPass(const GLRStep &step) { @@ -236,6 +369,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { int attrMask = 0; + // TODO: We can implement state-filtering locally in this function, to mimic the old gl state tracker, + // to avoid redundant calls. Might be worth it? + auto &commands = step.commands; for (const auto &c : commands) { switch (c.cmd) { @@ -445,6 +581,13 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy); } break; + case GLRRenderCommand::TEXTURELOD: + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, c.textureLod.minLod); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod); +#ifndef USING_GLES2 + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias); +#endif + break; case GLRRenderCommand::RASTER: if (c.raster.cullEnable) { glEnable(GL_CULL_FACE); @@ -498,13 +641,16 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) { switch (step.copy.aspectMask) { case GL_COLOR_BUFFER_BIT: - srcTex = src->color.texture; - dstTex = dst->color.texture; + srcTex = src->color_texture; + dstTex = dst->color_texture; break; case GL_DEPTH_BUFFER_BIT: + _assert_msg_(G3D, false, "Depth copies not yet supported - soon"); target = GL_RENDERBUFFER; + /* srcTex = src->depth.texture; dstTex = src->depth.texture; + */ break; } #if defined(USING_GLES2) @@ -546,6 +692,59 @@ void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) { curFBWidth_ = targetWidth_; curFBHeight_ = targetHeight_; } + +#if 0 + + CHECK_GL_ERROR_IF_DEBUG(); + curFB_ = (OpenGLFramebuffer *)fbo; + if (fbo) { + OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; + // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing + // in ES 2.0 that actually separate them anyway of course, so doesn't matter. + fbo_bind_fb_target(false, fb->handle); + // Always restore viewport after render target binding. Works around driver bugs. + glstate.viewport.restore(); + } else { + fbo_unbind(); + } + int clearFlags = 0; + if (rp.color == RPAction::CLEAR) { + float fc[4]{}; + if (rp.clearColor) { + Uint8x4ToFloat4(fc, rp.clearColor); + } + glClearColor(fc[0], fc[1], fc[2], fc[3]); + clearFlags |= GL_COLOR_BUFFER_BIT; + glstate.colorMask.force(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + if (rp.depth == RPAction::CLEAR) { +#ifdef USING_GLES2 + glClearDepthf(rp.clearDepth); +#else + glClearDepth(rp.clearDepth); +#endif + glClearStencil(rp.clearStencil); + clearFlags |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; + glstate.depthWrite.force(GL_TRUE); + glstate.stencilFunc.force(GL_ALWAYS, 0, 0); + glstate.stencilMask.force(0xFF); + } + if (clearFlags) { + glstate.scissorTest.force(false); + glClear(clearFlags); + glstate.scissorTest.restore(); + } + if (rp.color == RPAction::CLEAR) { + glstate.colorMask.restore(); + } + if (rp.depth == RPAction::CLEAR) { + glstate.depthWrite.restore(); + glstate.stencilFunc.restore(); + glstate.stencilMask.restore(); + } + CHECK_GL_ERROR_IF_DEBUG(); +#endif + } void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { @@ -562,3 +761,157 @@ GLuint GLQueueRunner::AllocTextureName() { return name; } + +// On PC, we always use GL_DEPTH24_STENCIL8. +// On Android, we try to use what's available. + +#ifndef USING_GLES2 +void GLQueueRunner::fbo_ext_create(const GLRInitStep &step) { + GLRFramebuffer *fbo = step.create_framebuffer.framebuffer; + + // Color texture is same everywhere + glGenFramebuffersEXT(1, &fbo->handle); + glGenTextures(1, &fbo->color_texture); + + // Create the surfaces. + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + 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_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + 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_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + fbo->stencil_buffer = 0; + fbo->z_buffer = 0; + // 24-bit Z, 8-bit stencil + glGenRenderbuffersEXT(1, &fbo->z_stencil_buffer); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, fbo->width, fbo->height); + //glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, width, height); + + // Bind it all together + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); + + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + switch (status) { + case GL_FRAMEBUFFER_COMPLETE_EXT: + // ILOG("Framebuffer verified complete."); + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); + break; + default: + FLOG("Other framebuffer error: %i", status); + break; + } + // Unbind state we don't need + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + glBindTexture(GL_TEXTURE_2D, 0); + + currentDrawHandle_ = fbo->handle; + currentReadHandle_ = fbo->handle; +} +#endif + +GLenum GLQueueRunner::fbo_get_fb_target(bool read, GLuint **cached) { + bool supportsBlit = gl_extensions.ARB_framebuffer_object; + if (gl_extensions.IsGLES) { + supportsBlit = (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit); + } + + // Note: GL_FRAMEBUFFER_EXT and GL_FRAMEBUFFER have the same value, same with _NV. + if (supportsBlit) { + if (read) { + *cached = ¤tReadHandle_; + return GL_READ_FRAMEBUFFER; + } else { + *cached = ¤tDrawHandle_; + return GL_DRAW_FRAMEBUFFER; + } + } else { + *cached = ¤tDrawHandle_; + return GL_FRAMEBUFFER; + } +} + +void GLQueueRunner::fbo_bind_fb_target(bool read, GLuint name) { + GLuint *cached; + GLenum target = fbo_get_fb_target(read, &cached); + if (*cached != name) { + if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { + glBindFramebuffer(target, name); + } else { +#ifndef USING_GLES2 + glBindFramebufferEXT(target, name); +#endif + } + *cached = name; + } +} + +void GLQueueRunner::fbo_unbind() { +#ifndef USING_GLES2 + if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { + glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO); + } else if (gl_extensions.EXT_framebuffer_object) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_defaultFBO); + } +#else + glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO); +#endif + +#ifdef IOS + bindDefaultFBO(); +#endif + + currentDrawHandle_ = 0; + currentReadHandle_ = 0; +} + +GLRFramebuffer::~GLRFramebuffer() { + if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { + if (handle) { + glBindFramebuffer(GL_FRAMEBUFFER, handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO); + glDeleteFramebuffers(1, &handle); + } + if (z_stencil_buffer) + glDeleteRenderbuffers(1, &z_stencil_buffer); + if (z_buffer) + glDeleteRenderbuffers(1, &z_buffer); + if (stencil_buffer) + glDeleteRenderbuffers(1, &stencil_buffer); + } else if (gl_extensions.EXT_framebuffer_object) { +#ifndef USING_GLES2 + if (handle) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, handle); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_defaultFBO); + glDeleteFramebuffersEXT(1, &handle); + } + if (z_stencil_buffer) + glDeleteRenderbuffers(1, &z_stencil_buffer); + if (z_buffer) + glDeleteRenderbuffers(1, &z_buffer); + if (stencil_buffer) + glDeleteRenderbuffers(1, &stencil_buffer); +#endif + } + + glDeleteTextures(1, &color_texture); +} \ No newline at end of file diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index f26d995d5e..e01a80075a 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -36,6 +36,7 @@ enum class GLRRenderCommand : uint8_t { UNIFORM4F, UNIFORMMATRIX, TEXTURESAMPLER, + TEXTURELOD, VIEWPORT, SCISSOR, RASTER, @@ -143,6 +144,11 @@ struct GLRRenderData { GLenum minFilter; // also includes mip. GL... float anisotropy; } textureSampler; + struct { + float minLod; + float maxLod; + float lodBias; + } textureLod; struct { GLRViewport vp; } viewport; @@ -307,6 +313,8 @@ public: targetHeight_ = height; } private: + void InitCreateFramebuffer(const GLRInitStep &step); + void PerformBindFramebufferAsRenderTarget(const GLRStep &pass); void PerformRenderPass(const GLRStep &pass); void PerformCopy(const GLRStep &pass); @@ -322,6 +330,12 @@ private: void ResizeReadbackBuffer(size_t requiredSize); + void fbo_ext_create(const GLRInitStep &step); + void fbo_bind_fb_target(bool read, GLuint name); + GLenum fbo_get_fb_target(bool read, GLuint **cached); + void fbo_unbind(); + + GLuint globalVAO_; GLint curFramebuffer_ = 0; @@ -337,6 +351,10 @@ private: float maxAnisotropyLevel_; + // Framebuffer state? + GLuint currentDrawHandle_ = 0; + GLuint currentReadHandle_ = 0; + GLuint AllocTextureName(); // Texture name cache. Ripped straight from TextureCacheGLES. std::vector nameCache_; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 167359eaeb..e00f11f7b3 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -1,6 +1,7 @@ #include #include "GLRenderManager.h" +#include "gfx_es2/gpu_features.h" #include "thread/threadutil.h" #include "base/logging.h" @@ -10,10 +11,6 @@ #define VLOG(...) #endif -void GLCreateImage(GLRImage &img, int width, int height, GLuint format, bool color) { - -} - void GLDeleter::Perform() { for (auto shader : shaders) { delete shader; @@ -21,7 +18,18 @@ void GLDeleter::Perform() { for (auto program : programs) { delete program; } - // .. + for (auto buffer : buffers) { + delete buffer; + } + for (auto texture : textures) { + delete texture; + } + for (auto inputLayout : inputLayouts) { + delete inputLayout; + } + for (auto framebuffer : framebuffers) { + delete framebuffer; + } } GLRenderManager::GLRenderManager() { diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index b014302f52..34bc3d238b 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -11,13 +11,6 @@ #include "Common/Log.h" #include "GLQueueRunner.h" -struct GLRImage { - GLuint texture; - GLuint format; -}; - -void GLCreateImage(GLRImage &img, int width, int height, GLint format, bool color); - class GLRInputLayout; class GLRFramebuffer { @@ -26,18 +19,21 @@ public: : width(_width), height(_height), z_stencil_(z_stencil) { } - ~GLRFramebuffer() { - glDeleteTextures(1, &color.texture); - glDeleteRenderbuffers(1, &depth.texture); - } + ~GLRFramebuffer(); int numShadows = 1; // TODO: Support this. + GLuint handle = 0; + GLuint color_texture = 0; + GLuint z_stencil_buffer = 0; // Either this is set, or the two below. + GLuint z_buffer = 0; + GLuint stencil_buffer = 0; + + int width; + int height; + GLuint colorDepth; + GLuint framebuf = 0; - GLRImage color{}; - GLRImage depth{}; - int width = 0; - int height = 0; bool z_stencil_; }; @@ -144,6 +140,13 @@ public: buffers = std::move(other.buffers); textures = std::move(other.textures); inputLayouts = std::move(other.inputLayouts); + framebuffers = std::move(other.framebuffers); + other.shaders.clear(); + other.programs.clear(); + other.buffers.clear(); + other.textures.clear(); + other.inputLayouts.clear(); + other.framebuffers.clear(); } std::vector shaders; @@ -151,6 +154,7 @@ public: std::vector buffers; std::vector textures; std::vector inputLayouts; + std::vector framebuffers; }; class GLRInputLayout { @@ -272,6 +276,9 @@ public: void DeleteInputLayout(GLRInputLayout *inputLayout) { deleter_.inputLayouts.push_back(inputLayout); } + void DeleteFramebuffer(GLRFramebuffer *framebuffer) { + deleter_.framebuffers.push_back(framebuffer); + } void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil); void BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment); @@ -519,6 +526,15 @@ public: curRenderStep_->commands.push_back(data); } + void SetTextureLod(float minLod, float maxLod, float lodBias) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::TEXTURELOD}; + data.textureLod.minLod = minLod; + data.textureLod.maxLod = maxLod; + data.textureLod.lodBias = lodBias; + curRenderStep_->commands.push_back(data); + } + void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::CLEAR }; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index cc0fb5299c..ee6b366516 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -21,12 +21,6 @@ extern void bindDefaultFBO(); // #define DEBUG_READ_PIXELS 1 -// Workaround for Retroarch. Simply declare -// extern GLuint g_defaultFBO; -// and set is as appropriate. Can adjust the variables in ext/native/base/display.h as -// appropriate. -GLuint g_defaultFBO = 0; - namespace Draw { static const unsigned short compToGL[] = { @@ -483,10 +477,6 @@ public: void HandleEvent(Event ev, int width, int height, void *param1, void *param2) override {} private: - OpenGLFramebuffer *fbo_ext_create(const FramebufferDesc &desc); - void fbo_bind_fb_target(bool read, GLuint name); - GLenum fbo_get_fb_target(bool read, GLuint **cached); - void fbo_unbind(); void ApplySamplers(); GLRenderManager renderManager_; @@ -504,10 +494,6 @@ private: int curIBufferOffset_ = 0; OpenGLFramebuffer *curFB_; - // Framebuffer state - GLuint currentDrawHandle_ = 0; - GLuint currentReadHandle_ = 0; - // Frames in flight is not such a strict concept as with Vulkan until we start using glBufferStorage and fences. // But might as well have the structure ready, and can't hurt to rotate buffers. struct FrameData { @@ -652,16 +638,6 @@ OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : } mipLevels_ = desc.generateMips ? desc.mipLevels : level; - /* -#ifdef USING_GLES2 - if (gl_extensions.GLES3) { - glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, mipLevels_ - 1); - } -#else - glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, mipLevels_ - 1); -#endif -*/ - if ((int)desc.initData.size() < desc.mipLevels && desc.generateMips) { ILOG("Generating mipmaps"); AutoGenMipmaps(); @@ -687,19 +663,14 @@ void OpenGLTexture::AutoGenMipmaps() { class OpenGLFramebuffer : public Framebuffer { public: - OpenGLFramebuffer() {} - ~OpenGLFramebuffer(); + OpenGLFramebuffer(GLRenderManager *render) : render_(render) {} + ~OpenGLFramebuffer() { + render_->DeleteFramebuffer(framebuffer); + } + GLRenderManager *render_; GLRFramebuffer *framebuffer; - GLuint handle = 0; - GLuint color_texture = 0; - GLuint z_stencil_buffer = 0; // Either this is set, or the two below. - GLuint z_buffer = 0; - GLuint stencil_buffer = 0; - - int width; - int height; FBColorDepth colorDepth; }; @@ -852,6 +823,7 @@ static void LogReadPixelsError(GLenum error) { bool OpenGLContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat dataFormat, void *pixels, int pixelStride) { OpenGLFramebuffer *fb = (OpenGLFramebuffer *)src; + /* fbo_bind_fb_target(true, fb ? fb->handle : 0); // Reads from the "bound for read" framebuffer. @@ -883,6 +855,7 @@ bool OpenGLContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBit glPixelStorei(GL_PACK_ROW_LENGTH, 0); } CHECK_GL_ERROR_IF_DEBUG(); + */ return true; } @@ -1245,335 +1218,20 @@ void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) { inputLayout_ = render_->CreateInputLayout(entries); } -// On PC, we always use GL_DEPTH24_STENCIL8. -// On Android, we try to use what's available. - -#ifndef USING_GLES2 -OpenGLFramebuffer *OpenGLContext::fbo_ext_create(const FramebufferDesc &desc) { - OpenGLFramebuffer *fbo = new OpenGLFramebuffer(); - fbo->width = desc.width; - fbo->height = desc.height; - fbo->colorDepth = desc.colorDepth; - - // Color texture is same everywhere - glGenFramebuffersEXT(1, &fbo->handle); - glGenTextures(1, &fbo->color_texture); - - // Create the surfaces. - glBindTexture(GL_TEXTURE_2D, fbo->color_texture); - 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_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // TODO: We could opt to only create 16-bit render targets on slow devices. For later. - switch (fbo->colorDepth) { - case FBO_8888: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - break; - case FBO_4444: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL); - break; - case FBO_5551: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL); - break; - case FBO_565: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fbo->width, fbo->height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); - break; - } - - 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_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - fbo->stencil_buffer = 0; - fbo->z_buffer = 0; - // 24-bit Z, 8-bit stencil - glGenRenderbuffersEXT(1, &fbo->z_stencil_buffer); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, fbo->width, fbo->height); - //glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, width, height); - - // Bind it all together - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); - - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - switch (status) { - case GL_FRAMEBUFFER_COMPLETE_EXT: - // ILOG("Framebuffer verified complete."); - break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: - ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); - break; - default: - FLOG("Other framebuffer error: %i", status); - break; - } - // Unbind state we don't need - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - glBindTexture(GL_TEXTURE_2D, 0); - - currentDrawHandle_ = fbo->handle; - currentReadHandle_ = fbo->handle; - return fbo; -} -#endif - Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) { CheckGLExtensions(); - OpenGLFramebuffer *fbo = new OpenGLFramebuffer(); - // fbo->framebuffer = renderManager_.CreateFramebuffer() - -#ifndef USING_GLES2 - if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) { - return fbo_ext_create(desc); - } else if (!gl_extensions.ARB_framebuffer_object) { - return nullptr; - } - // If GLES2, we have basic FBO support and can just proceed. -#endif - CHECK_GL_ERROR_IF_DEBUG(); - - fbo->width = desc.width; - fbo->height = desc.height; - fbo->colorDepth = desc.colorDepth; - - // Color texture is same everywhere - glGenFramebuffers(1, &fbo->handle); - glGenTextures(1, &fbo->color_texture); - - // Create the surfaces. - glBindTexture(GL_TEXTURE_2D, fbo->color_texture); - 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_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // TODO: We could opt to only create 16-bit render targets on slow devices. For later. - switch (fbo->colorDepth) { - case FBO_8888: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - break; - case FBO_4444: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL); - break; - case FBO_5551: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL); - break; - case FBO_565: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fbo->width, fbo->height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); - break; - } - - 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_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - if (gl_extensions.IsGLES) { - if (gl_extensions.OES_packed_depth_stencil) { - ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", fbo->width, fbo->height); - // Standard method - fbo->stencil_buffer = 0; - fbo->z_buffer = 0; - // 24-bit Z, 8-bit stencil combined - glGenRenderbuffers(1, &fbo->z_stencil_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, fbo->width, fbo->height); - - // Bind it all together - glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - } else { - ILOG("Creating %i x %i FBO using separate stencil", fbo->width, fbo->height); - // TEGRA - fbo->z_stencil_buffer = 0; - // 16/24-bit Z, separate 8-bit stencil - glGenRenderbuffers(1, &fbo->z_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer); - // Don't forget to make sure fbo_standard_z_depth() matches. - glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, fbo->width, fbo->height); - - // 8-bit stencil buffer - glGenRenderbuffers(1, &fbo->stencil_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, fbo->width, fbo->height); - - // Bind it all together - glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer); - } - } else { - fbo->stencil_buffer = 0; - fbo->z_buffer = 0; - // 24-bit Z, 8-bit stencil - glGenRenderbuffers(1, &fbo->z_stencil_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, fbo->width, fbo->height); - - // Bind it all together - glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - } - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - switch (status) { - case GL_FRAMEBUFFER_COMPLETE: - // ILOG("Framebuffer verified complete."); - break; - case GL_FRAMEBUFFER_UNSUPPORTED: - ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); - break; - default: - FLOG("Other framebuffer error: %i", status); - break; - } - - // Unbind state we don't need - glBindRenderbuffer(GL_RENDERBUFFER, 0); - glBindTexture(GL_TEXTURE_2D, 0); - CHECK_GL_ERROR_IF_DEBUG(); - - currentDrawHandle_ = fbo->handle; - currentReadHandle_ = fbo->handle; + OpenGLFramebuffer *fbo = new OpenGLFramebuffer(&renderManager_); + fbo->framebuffer = renderManager_.CreateFramebuffer(desc.width, desc.height, desc.z_stencil); return fbo; } -GLenum OpenGLContext::fbo_get_fb_target(bool read, GLuint **cached) { - bool supportsBlit = gl_extensions.ARB_framebuffer_object; - if (gl_extensions.IsGLES) { - supportsBlit = (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit); - } - - // Note: GL_FRAMEBUFFER_EXT and GL_FRAMEBUFFER have the same value, same with _NV. - if (supportsBlit) { - if (read) { - *cached = ¤tReadHandle_; - return GL_READ_FRAMEBUFFER; - } else { - *cached = ¤tDrawHandle_; - return GL_DRAW_FRAMEBUFFER; - } - } else { - *cached = ¤tDrawHandle_; - return GL_FRAMEBUFFER; - } -} - -void OpenGLContext::fbo_bind_fb_target(bool read, GLuint name) { - GLuint *cached; - GLenum target = fbo_get_fb_target(read, &cached); - if (*cached != name) { - if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { - glBindFramebuffer(target, name); - } else { -#ifndef USING_GLES2 - glBindFramebufferEXT(target, name); -#endif - } - *cached = name; - } -} - -void OpenGLContext::fbo_unbind() { -#ifndef USING_GLES2 - if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { - glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO); - } else if (gl_extensions.EXT_framebuffer_object) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_defaultFBO); - } -#else - glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO); -#endif - -#ifdef IOS - bindDefaultFBO(); -#endif - - currentDrawHandle_ = 0; - currentReadHandle_ = 0; -} - void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp) { OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; GLRRenderPassAction color = (GLRRenderPassAction)rp.color; GLRRenderPassAction depth = (GLRRenderPassAction)rp.depth; renderManager_.BindFramebufferAsRenderTarget(fb ? fb->framebuffer : nullptr, color, depth, rp.clearColor, rp.clearDepth, rp.clearStencil); - -#if 0 - - CHECK_GL_ERROR_IF_DEBUG(); - curFB_ = (OpenGLFramebuffer *)fbo; - if (fbo) { - OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; - // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing - // in ES 2.0 that actually separate them anyway of course, so doesn't matter. - fbo_bind_fb_target(false, fb->handle); - // Always restore viewport after render target binding. Works around driver bugs. - glstate.viewport.restore(); - } else { - fbo_unbind(); - } - int clearFlags = 0; - if (rp.color == RPAction::CLEAR) { - float fc[4]{}; - if (rp.clearColor) { - Uint8x4ToFloat4(fc, rp.clearColor); - } - glClearColor(fc[0], fc[1], fc[2], fc[3]); - clearFlags |= GL_COLOR_BUFFER_BIT; - glstate.colorMask.force(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } - if (rp.depth == RPAction::CLEAR) { -#ifdef USING_GLES2 - glClearDepthf(rp.clearDepth); -#else - glClearDepth(rp.clearDepth); -#endif - clearFlags |= GL_DEPTH_BUFFER_BIT; - glstate.depthWrite.force(GL_TRUE); - } - if (rp.stencil == RPAction::CLEAR) { - glClearStencil(rp.clearStencil); - clearFlags |= GL_STENCIL_BUFFER_BIT; - glstate.stencilFunc.force(GL_ALWAYS, 0, 0); - glstate.stencilMask.force(0xFF); - } - if (clearFlags) { - glstate.scissorTest.force(false); - glClear(clearFlags); - glstate.scissorTest.restore(); - } - if (rp.color == RPAction::CLEAR) { - glstate.colorMask.restore(); - } - if (rp.depth == RPAction::CLEAR) { - glstate.depthWrite.restore(); - } - if (rp.stencil == RPAction::CLEAR) { - glstate.stencilFunc.restore(); - glstate.stencilMask.restore(); - } - CHECK_GL_ERROR_IF_DEBUG(); -#endif } void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) { @@ -1604,24 +1262,6 @@ bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, in aspect |= GL_STENCIL_BUFFER_BIT; renderManager_.BlitFramebuffer(src->framebuffer, GLRect2D{ srcX1, srcY1, srcX2 - srcX1, srcY2 - srcY1 }, dst->framebuffer, GLRect2D{ dstX1, dstY1, dstX2 - dstX1, dstY2 - dstY1 }, aspect, linearFilter == FB_BLIT_LINEAR); - /* - // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing - // in ES 2.0 that actually separate them anyway of course, so doesn't matter. - fbo_bind_fb_target(false, dst->handle); - fbo_bind_fb_target(true, src->handle); - if (gl_extensions.GLES3 || gl_extensions.ARB_framebuffer_object) { - glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, aspect, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST); - CHECK_GL_ERROR_IF_DEBUG(); -#if defined(USING_GLES2) && defined(__ANDROID__) // We only support this extension on Android, it's not even available on PC. - return true; - } else if (gl_extensions.NV_framebuffer_blit) { - glBlitFramebufferNV(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, aspect, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST); - CHECK_GL_ERROR_IF_DEBUG(); -#endif // defined(USING_GLES2) && defined(__ANDROID__) - return true; - } else { - return false; - }*/ return true; } @@ -1632,48 +1272,11 @@ void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBCh renderManager_.BindFramebufferAsTexture(fb->framebuffer, binding, (int)channelBit, color); } -OpenGLFramebuffer::~OpenGLFramebuffer() { - CHECK_GL_ERROR_IF_DEBUG(); - if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { - if (handle) { - glBindFramebuffer(GL_FRAMEBUFFER, handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); - glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO); - glDeleteFramebuffers(1, &handle); - } - if (z_stencil_buffer) - glDeleteRenderbuffers(1, &z_stencil_buffer); - if (z_buffer) - glDeleteRenderbuffers(1, &z_buffer); - if (stencil_buffer) - glDeleteRenderbuffers(1, &stencil_buffer); - } else if (gl_extensions.EXT_framebuffer_object) { -#ifndef USING_GLES2 - if (handle) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, handle); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_defaultFBO); - glDeleteFramebuffersEXT(1, &handle); - } - if (z_stencil_buffer) - glDeleteRenderbuffers(1, &z_stencil_buffer); - if (z_buffer) - glDeleteRenderbuffers(1, &z_buffer); - if (stencil_buffer) - glDeleteRenderbuffers(1, &stencil_buffer); -#endif - } - - glDeleteTextures(1, &color_texture); -} - void OpenGLContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) { OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; if (fb) { - *w = fb->width; - *h = fb->height; + *w = fb->framebuffer->width; + *h = fb->framebuffer->height; } else { *w = targetWidth_; *h = targetHeight_; From 8a1e7347b9ab83dd8dbe610c066514654c049a86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 14 Dec 2017 14:53:27 +0100 Subject: [PATCH 016/291] GL render manager: Various fixes and cleanup including a buffered rendering fix, rect primitive fix --- GPU/Common/FramebufferCommon.cpp | 7 -- GPU/GLES/DepalettizeShaderGLES.cpp | 31 ------ GPU/GLES/DrawEngineGLES.cpp | 2 +- GPU/GLES/FramebufferManagerGLES.cpp | 84 +++----------- GPU/GLES/FramebufferManagerGLES.h | 2 +- ext/native/thin3d/GLQueueRunner.cpp | 151 +++++++++++++++----------- ext/native/thin3d/GLQueueRunner.h | 6 +- ext/native/thin3d/GLRenderManager.cpp | 2 - ext/native/thin3d/GLRenderManager.h | 23 +++- ext/native/thin3d/thin3d_gl.cpp | 8 +- 10 files changed, 134 insertions(+), 182 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index a54e58c61e..7425c88761 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -1032,13 +1032,6 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { SetViewport2D(0, 0, pixelWidth_, pixelHeight_); DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, uvRotation, flags); } - - /* - if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) { - draw_->BindFramebufferAsRenderTarget(extraFBOs_[0], { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); - GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT }; - glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments); - }*/ } else { draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); draw_->BindFramebufferAsTexture(vfb->fbo, 0, Draw::FB_COLOR_BIT, 0); diff --git a/GPU/GLES/DepalettizeShaderGLES.cpp b/GPU/GLES/DepalettizeShaderGLES.cpp index b4eff02b9d..6ea73043a1 100644 --- a/GPU/GLES/DepalettizeShaderGLES.cpp +++ b/GPU/GLES/DepalettizeShaderGLES.cpp @@ -57,37 +57,6 @@ static const char *depalVShader300 = " gl_Position = a_position;\n" "}\n"; - -static bool CheckShaderCompileSuccess(GLuint shader, const char *code) { - GLint success; - glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - if (!success) { -#define MAX_INFO_LOG_SIZE 2048 - GLchar infoLog[MAX_INFO_LOG_SIZE]; - GLsizei len; - glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog); - infoLog[len] = '\0'; -#ifdef __ANDROID__ - ELOG("Error in shader compilation! %s\n", infoLog); - ELOG("Shader source:\n%s\n", (const char *)code); -#endif - ERROR_LOG(G3D, "Error in shader compilation!\n"); - ERROR_LOG(G3D, "Info log: %s\n", infoLog); - ERROR_LOG(G3D, "Shader source:\n%s\n", (const char *)code); -#ifdef SHADERLOG - OutputDebugStringUTF8(infoLog); -#endif - shader = 0; - return false; - } else { - DEBUG_LOG(G3D, "Compiled shader:\n%s\n", (const char *)code); -#ifdef SHADERLOG - OutputDebugStringUTF8(code); -#endif - return true; - } -} - DepalShaderCacheGLES::DepalShaderCacheGLES(Draw::DrawContext *draw) { render_ = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); // Pre-build the vertex program diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index e61f7df9d0..92efcc43fb 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -656,7 +656,7 @@ rotateVBO: if (drawIndexed) { vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(drawBuffer, maxIndex * sizeof(TransformedVertex), &vertexBuffer); - indexBufferOffset = (uint32_t)frameData.pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), &indexBuffer); + indexBufferOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(uint16_t) * numTrans, &indexBuffer); render_->BindVertexBuffer(vertexBuffer); render_->BindInputLayout(softwareInputLayout_, (void *)(intptr_t)vertexBufferOffset); render_->BindIndexBuffer(indexBuffer); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 96e8ef5d7f..2f033d736c 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -81,18 +81,6 @@ const int MAX_PBO = 2; void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format); void FramebufferManagerGLES::DisableState() { - /* - glstate.blend.disable(); - glstate.cullFace.disable(); - glstate.depthTest.disable(); - glstate.scissorTest.disable(); - glstate.stencilTest.disable(); -#if !defined(USING_GLES2) - glstate.colorLogicOp.disable(); -#endif - glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glstate.stencilMask.set(0xFF); - */ gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); } @@ -293,7 +281,7 @@ void FramebufferManagerGLES::CreateDeviceObjects() { std::vector entries; entries.push_back({ 0, 3, GL_FLOAT, GL_FALSE, sizeof(Simple2DVertex), offsetof(Simple2DVertex, pos) }); - entries.push_back({ 0, 2, GL_FLOAT, GL_FALSE, sizeof(Simple2DVertex), offsetof(Simple2DVertex, uv) }); + entries.push_back({ 1, 2, GL_FLOAT, GL_FALSE, sizeof(Simple2DVertex), offsetof(Simple2DVertex, uv) }); simple2DInputLayout_ = render_->CreateInputLayout(entries); } @@ -326,7 +314,9 @@ FramebufferManagerGLES::~FramebufferManagerGLES() { if (pixelBufObj_) { for (int i = 0; i < MAX_PBO; i++) { - glDeleteBuffers(1, &pixelBufObj_[i].handle); + if (pixelBufObj_[i].buffer) { + render_->DeleteBuffer(pixelBufObj_[i].buffer); + } } delete[] pixelBufObj_; } @@ -357,9 +347,7 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma render_->BindTexture(0, drawPixelsTex_); render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); - /* - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - */ + // render_->TextureImage(drawPixelsTex_, 0, drawPixelsTexW_, drawPixelsTexH_, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); drawPixelsTexFormat_ = srcPixelFormat; } else { render_->BindTexture(0, drawPixelsTex_); @@ -463,11 +451,6 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); } - const GLSLProgram *program = glsl_get_program(); - if (!program) { - ERROR_LOG(FRAMEBUF, "Trying to DrawActiveTexture() without a program"); - return; - } Simple2DVertex verts[4]; memcpy(verts[0].pos, &pos[0], 12); memcpy(verts[1].pos, &pos[3], 12); @@ -642,7 +625,6 @@ void FramebufferManagerGLES::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) } else if (gl_extensions.IsGLES) { draw_->BindFramebufferAsRenderTarget(nvfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); } - CHECK_GL_ERROR_IF_DEBUG(); } void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) { @@ -695,7 +677,6 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, const bool yOverlap = src == dst && srcY2 > dstY1 && srcY1 < dstY2; if (sameSize && sameDepth && srcInsideBounds && dstInsideBounds && !(xOverlap && yOverlap)) { draw_->CopyFramebufferImage(src->fbo, 0, srcX1, srcY1, 0, dst->fbo, 0, dstX1, dstY1, 0, dstX2 - dstX1, dstY2 - dstY1, 1, Draw::FB_COLOR_BIT); - CHECK_GL_ERROR_IF_DEBUG(); return; } } @@ -724,7 +705,6 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, } gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_RASTER_STATE); - CHECK_GL_ERROR_IF_DEBUG(); } // TODO: SSE/NEON @@ -785,7 +765,6 @@ void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u } void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) { - CHECK_GL_ERROR_IF_DEBUG(); GLubyte *packed = 0; bool unbind = false; const u8 nextPBO = (currentPBO_ + 1) % MAX_PBO; @@ -799,21 +778,13 @@ void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) { return; } - GLuint pbos[MAX_PBO]; - glGenBuffers(MAX_PBO, pbos); - - pixelBufObj_ = new AsyncPBO[MAX_PBO]; - for (int i = 0; i < MAX_PBO; i++) { - pixelBufObj_[i].handle = pbos[i]; - pixelBufObj_[i].maxSize = 0; - pixelBufObj_[i].reading = false; - } + pixelBufObj_ = new AsyncPBO[MAX_PBO]{}; } // Receive previously requested data from a PBO AsyncPBO &pbo = pixelBufObj_[nextPBO]; if (pbo.reading) { - glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo.handle); + render_->BindPixelPackBuffer(pbo.buffer); #ifdef USING_GLES2 // Not on desktop GL 2.x... packed = (GLubyte *)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, pbo.size, GL_MAP_READ_BIT); @@ -875,14 +846,15 @@ void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) { return; } - 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); + if (pixelBufObj_[currentPBO_].buffer) { + render_->DeleteBuffer(pixelBufObj_[currentPBO_].buffer); + } + pixelBufObj_[currentPBO_].buffer = render_->CreateBuffer(GL_PIXEL_PACK_BUFFER, bufSize, GL_DYNAMIC_READ); pixelBufObj_[currentPBO_].maxSize = bufSize; } + render_->BindPixelPackBuffer(pixelBufObj_[currentPBO_].buffer); // TODO: This is a hack since PBOs have not been implemented in Thin3D yet (and maybe shouldn't? maybe should do this internally?) draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, 0, 0, vfb->fb_stride, vfb->height, dataFmt, nullptr, vfb->fb_stride); @@ -899,9 +871,8 @@ void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) { currentPBO_ = nextPBO; if (unbind) { - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + render_->BindPixelPackBuffer(0); } - CHECK_GL_ERROR_IF_DEBUG(); } void FramebufferManagerGLES::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h) { @@ -995,26 +966,9 @@ void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int } } } - CHECK_GL_ERROR_IF_DEBUG(); } void FramebufferManagerGLES::EndFrame() { - CHECK_GL_ERROR_IF_DEBUG(); - - // Let's explicitly invalidate any temp FBOs used during this frame. - if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) { - for (auto temp : tempFBOs_) { - if (temp.second.last_frame_used < gpuStats.numFlips) { - continue; - } - - draw_->BindFramebufferAsRenderTarget(temp.second.fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); - GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT }; - glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments); - } - draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP , Draw::RPAction::KEEP, Draw::RPAction::KEEP }); - } - CHECK_GL_ERROR_IF_DEBUG(); } void FramebufferManagerGLES::DeviceLost() { @@ -1028,7 +982,6 @@ void FramebufferManagerGLES::DeviceRestore(Draw::DrawContext *draw) { } void FramebufferManagerGLES::DestroyAllFBOs() { - CHECK_GL_ERROR_IF_DEBUG(); currentRenderVfb_ = 0; displayFramebuf_ = 0; prevDisplayFramebuf_ = 0; @@ -1055,7 +1008,6 @@ void FramebufferManagerGLES::DestroyAllFBOs() { SetNumExtraFBOs(0); DisableState(); - CHECK_GL_ERROR_IF_DEBUG(); } void FramebufferManagerGLES::Resized() { @@ -1066,15 +1018,7 @@ void FramebufferManagerGLES::Resized() { DestroyAllFBOs(); } -#ifndef USING_GLES2 - if (g_Config.iInternalResolution == 0) { - glLineWidth(std::max(1, (int)(renderWidth_ / 480))); - glPointSize(std::max(1.0f, (float)(renderWidth_ / 480.f))); - } else { - glLineWidth(g_Config.iInternalResolution); - glPointSize((float)g_Config.iInternalResolution); - } -#endif + // render_->SetLineWidth(renderWidth_ / 480.0f); } bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) { diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 57111e3fa2..60c5c841ad 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -38,7 +38,7 @@ class ShaderManagerGLES; // Simple struct for asynchronous PBO readbacks struct AsyncPBO { - uint32_t handle; + GLRBuffer *buffer; u32 maxSize; u32 fb_address; diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 7c8f61d3c5..9596b8c769 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -28,6 +28,9 @@ void GLQueueRunner::DestroyDeviceObjects() { } void GLQueueRunner::RunInitSteps(const std::vector &steps) { + glActiveTexture(GL_TEXTURE0); + GLuint boundTexture = (GLuint)-1; + for (int i = 0; i < steps.size(); i++) { const GLRInitStep &step = steps[i]; switch (step.stepType) { @@ -36,6 +39,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { GLRTexture *tex = step.create_texture.texture; glGenTextures(1, &tex->texture); glBindTexture(tex->target, tex->texture); + boundTexture = tex->texture; break; } case GLRInitStepType::CREATE_BUFFER: @@ -162,6 +166,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { } case GLRInitStepType::CREATE_FRAMEBUFFER: { + boundTexture = (GLuint)-1; InitCreateFramebuffer(step); break; } @@ -171,6 +176,10 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { { GLRTexture *tex = step.texture_image.texture; CHECK_GL_ERROR_IF_DEBUG(); + if (boundTexture != step.texture_image.texture->texture) { + glBindTexture(step.texture_image.texture->target, step.texture_image.texture->texture); + boundTexture = step.texture_image.texture->texture; + } glTexImage2D(tex->target, step.texture_image.level, step.texture_image.internalFormat, step.texture_image.width, step.texture_image.height, 0, step.texture_image.format, step.texture_image.type, step.texture_image.data); delete[] step.texture_image.data; CHECK_GL_ERROR_IF_DEBUG(); @@ -182,6 +191,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { } default: Crash(); + break; } } } @@ -359,18 +369,30 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glEnable(GL_SCISSOR_TEST); + /* +#ifndef USING_GLES2 + if (g_Config.iInternalResolution == 0) { + glLineWidth(std::max(1, (int)(renderWidth_ / 480))); + glPointSize(std::max(1.0f, (float)(renderWidth_ / 480.f))); + } else { + glLineWidth(g_Config.iInternalResolution); + glPointSize((float)g_Config.iInternalResolution); + } +#endif + */ + glBindVertexArray(globalVAO_); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); GLRFramebuffer *fb = step.render.framebuffer; GLRProgram *curProgram = nullptr; - GLint activeTexture = GL_TEXTURE0; + int activeTexture = 0; + glActiveTexture(GL_TEXTURE0 + activeTexture); int attrMask = 0; - // TODO: We can implement state-filtering locally in this function, to mimic the old gl state tracker, - // to avoid redundant calls. Might be worth it? + // State filtering tracking. + GLuint curArrayBuffer = (GLuint)-1; + GLuint curElemArrayBuffer = (GLuint)-1; auto &commands = step.commands; for (const auto &c : commands) { @@ -415,6 +437,19 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glClear(c.clear.clearMask); glEnable(GL_SCISSOR_TEST); break; + case GLRRenderCommand::INVALIDATE: + { + GLenum attachments[3]; + int count = 0; + if (c.clear.clearMask & GL_COLOR_BUFFER_BIT) + attachments[count++] = GL_COLOR_ATTACHMENT0; + if (c.clear.clearMask & GL_DEPTH_BUFFER_BIT) + attachments[count++] = GL_DEPTH_ATTACHMENT; + if (c.clear.clearMask & GL_STENCIL_BUFFER_BIT) + attachments[count++] = GL_STENCIL_BUFFER_BIT; + glInvalidateFramebuffer(GL_FRAMEBUFFER, count, attachments); + break; + } case GLRRenderCommand::BLENDCOLOR: glBlendColor(c.blendColor.color[0], c.blendColor.color[1], c.blendColor.color[2], c.blendColor.color[3]); break; @@ -518,7 +553,21 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { if (c.texture.texture) { glBindTexture(c.texture.texture->target, c.texture.texture->texture); } else { - glBindTexture(GL_TEXTURE_2D, 0); // ? + glBindTexture(GL_TEXTURE_2D, 0); // Which target? Well we only use this one anyway... + } + break; + } + case GLRRenderCommand::BIND_FB_TEXTURE: + { + GLint slot = c.bind_fb_texture.slot; + if (slot != activeTexture) { + glActiveTexture(GL_TEXTURE0 + slot); + activeTexture = slot; + } + if (c.bind_fb_texture.aspect == GL_COLOR_BUFFER_BIT) { + glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->color_texture); + } else { + // TODO: Depth texturing? } break; } @@ -549,19 +598,28 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } break; } - case GLRRenderCommand::BIND_VERTEX_BUFFER: + case GLRRenderCommand::BIND_BUFFER: { - GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0; - glBindBuffer(GL_ARRAY_BUFFER, buf); - break; - } - case GLRRenderCommand::BIND_INDEX_BUFFER: - { - GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0; - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); + if (c.bind_buffer.target == GL_ARRAY_BUFFER) { + GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0; + if (buf != curArrayBuffer) { + glBindBuffer(GL_ARRAY_BUFFER, buf); + curArrayBuffer = buf; + } + } else if (c.bind_buffer.target == GL_ELEMENT_ARRAY_BUFFER) { + GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0; + if (buf != curElemArrayBuffer) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); + curElemArrayBuffer = buf; + } + } else { + GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0; + glBindBuffer(c.bind_buffer.target, buf); + } break; } case GLRRenderCommand::GENMIPS: + // TODO: Should we include the texture handle in the command? glGenerateMipmap(GL_TEXTURE_2D); break; case GLRRenderCommand::DRAW: @@ -614,12 +672,17 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } } - if (activeTexture != GL_TEXTURE0) + if (activeTexture != 0) glActiveTexture(GL_TEXTURE0); + + // Wipe out the current state. glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindVertexArray(0); glDisable(GL_SCISSOR_TEST); + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } void GLQueueRunner::PerformCopy(const GLRStep &step) { @@ -693,58 +756,15 @@ void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) { curFBHeight_ = targetHeight_; } -#if 0 - - CHECK_GL_ERROR_IF_DEBUG(); - curFB_ = (OpenGLFramebuffer *)fbo; - if (fbo) { - OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; + curFB_ = pass.render.framebuffer; + if (curFB_) { // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing // in ES 2.0 that actually separate them anyway of course, so doesn't matter. - fbo_bind_fb_target(false, fb->handle); - // Always restore viewport after render target binding. Works around driver bugs. - glstate.viewport.restore(); + fbo_bind_fb_target(false, curFB_->handle); } else { fbo_unbind(); + // Backbuffer is now bound. } - int clearFlags = 0; - if (rp.color == RPAction::CLEAR) { - float fc[4]{}; - if (rp.clearColor) { - Uint8x4ToFloat4(fc, rp.clearColor); - } - glClearColor(fc[0], fc[1], fc[2], fc[3]); - clearFlags |= GL_COLOR_BUFFER_BIT; - glstate.colorMask.force(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } - if (rp.depth == RPAction::CLEAR) { -#ifdef USING_GLES2 - glClearDepthf(rp.clearDepth); -#else - glClearDepth(rp.clearDepth); -#endif - glClearStencil(rp.clearStencil); - clearFlags |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; - glstate.depthWrite.force(GL_TRUE); - glstate.stencilFunc.force(GL_ALWAYS, 0, 0); - glstate.stencilMask.force(0xFF); - } - if (clearFlags) { - glstate.scissorTest.force(false); - glClear(clearFlags); - glstate.scissorTest.restore(); - } - if (rp.color == RPAction::CLEAR) { - glstate.colorMask.restore(); - } - if (rp.depth == RPAction::CLEAR) { - glstate.depthWrite.restore(); - glstate.stencilFunc.restore(); - glstate.stencilMask.restore(); - } - CHECK_GL_ERROR_IF_DEBUG(); -#endif - } void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { @@ -761,7 +781,6 @@ GLuint GLQueueRunner::AllocTextureName() { return name; } - // On PC, we always use GL_DEPTH24_STENCIL8. // On Android, we try to use what's available. @@ -847,6 +866,7 @@ GLenum GLQueueRunner::fbo_get_fb_target(bool read, GLuint **cached) { } void GLQueueRunner::fbo_bind_fb_target(bool read, GLuint name) { + CHECK_GL_ERROR_IF_DEBUG(); GLuint *cached; GLenum target = fbo_get_fb_target(read, &cached); if (*cached != name) { @@ -859,9 +879,11 @@ void GLQueueRunner::fbo_bind_fb_target(bool read, GLuint name) { } *cached = name; } + CHECK_GL_ERROR_IF_DEBUG(); } void GLQueueRunner::fbo_unbind() { + CHECK_GL_ERROR_IF_DEBUG(); #ifndef USING_GLES2 if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO); @@ -878,6 +900,7 @@ void GLQueueRunner::fbo_unbind() { currentDrawHandle_ = 0; currentReadHandle_ = 0; + CHECK_GL_ERROR_IF_DEBUG(); } GLRFramebuffer::~GLRFramebuffer() { diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index e01a80075a..e4c221b8e1 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -41,12 +41,12 @@ enum class GLRRenderCommand : uint8_t { SCISSOR, RASTER, CLEAR, + INVALIDATE, BINDPROGRAM, BINDTEXTURE, BIND_FB_TEXTURE, BIND_INPUT_LAYOUT, - BIND_VERTEX_BUFFER, - BIND_INDEX_BUFFER, + BIND_BUFFER, GENMIPS, DRAW, DRAW_INDEXED, @@ -129,6 +129,7 @@ struct GLRRenderData { } bind_fb_texture; struct { GLRBuffer *buffer; + GLuint target; } bind_buffer; struct { GLRProgram *program; @@ -335,6 +336,7 @@ private: GLenum fbo_get_fb_target(bool read, GLuint **cached); void fbo_unbind(); + GLRFramebuffer *curFB_ = nullptr; GLuint globalVAO_; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index e00f11f7b3..6bbae74b09 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -382,8 +382,6 @@ void GLPushBuffer::Unmap() { // Here we should simply upload everything to the buffers. // Might be worth trying with size_ instead of offset_, so the driver can replace the whole buffer. // At least if it's close. - if (offset_ > 0 && buffers_[buf_].deviceMemory[0] == 0xCD) - Crash(); render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].deviceMemory, false); writePtr_ = nullptr; } diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 34bc3d238b..c7dcc0b805 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -33,7 +33,6 @@ public: int height; GLuint colorDepth; - GLuint framebuf = 0; bool z_stencil_; }; @@ -330,21 +329,32 @@ public: void BindProgram(GLRProgram *program) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::BINDPROGRAM }; + _dbg_assert_(G3D, program != nullptr); data.program.program = program; curRenderStep_->commands.push_back(data); } void BindVertexBuffer(GLRBuffer *buffer) { // Want to support an offset but can't in ES 2.0. We supply an offset when binding the buffers instead. _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData data{ GLRRenderCommand::BIND_VERTEX_BUFFER }; + GLRRenderData data{ GLRRenderCommand::BIND_BUFFER }; data.bind_buffer.buffer = buffer; + data.bind_buffer.target = GL_ARRAY_BUFFER; + curRenderStep_->commands.push_back(data); + } + + void BindPixelPackBuffer(GLRBuffer *buffer) { // Want to support an offset but can't in ES 2.0. We supply an offset when binding the buffers instead. + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::BIND_BUFFER }; + data.bind_buffer.buffer = buffer; + data.bind_buffer.target = GL_PIXEL_PACK_BUFFER; curRenderStep_->commands.push_back(data); } void BindIndexBuffer(GLRBuffer *buffer) { // Want to support an offset but can't in ES 2.0. We supply an offset when binding the buffers instead. _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData data{ GLRRenderCommand::BIND_INDEX_BUFFER}; + GLRRenderData data{ GLRRenderCommand::BIND_BUFFER}; data.bind_buffer.buffer = buffer; + data.bind_buffer.target = GL_ELEMENT_ARRAY_BUFFER; curRenderStep_->commands.push_back(data); } @@ -545,6 +555,13 @@ public: curRenderStep_->commands.push_back(data); } + void Invalidate(int invalidateMask) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::INVALIDATE }; + data.clear.clearMask = invalidateMask; + curRenderStep_->commands.push_back(data); + } + void Draw(GLenum mode, int first, int count) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::DRAW }; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index ee6b366516..5b8ce4b45d 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -1269,7 +1269,13 @@ void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBCh OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; GLuint aspect = 0; - renderManager_.BindFramebufferAsTexture(fb->framebuffer, binding, (int)channelBit, color); + if (channelBit & FB_COLOR_BIT) + aspect |= GL_COLOR_BUFFER_BIT; + if (channelBit & FB_DEPTH_BIT) + aspect |= GL_DEPTH_BUFFER_BIT; + if (channelBit & FB_STENCIL_BIT) + aspect |= GL_STENCIL_BUFFER_BIT; + renderManager_.BindFramebufferAsTexture(fb->framebuffer, binding, aspect, color); } void OpenGLContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) { From 9094410fd17e0c8acc9e59ae16feb0d8ef2448cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 14 Dec 2017 16:08:55 +0100 Subject: [PATCH 017/291] gl-render-manager: Need to actually bind newly created textures. --- GPU/GLES/TextureCacheGLES.cpp | 2 ++ ext/native/thin3d/GLQueueRunner.cpp | 45 +++++++++++++++++---------- ext/native/thin3d/GLRenderManager.cpp | 11 +++++-- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index ddbc29b4bf..b6cd1cc038 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -690,6 +690,8 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag } // This will rebind it, but that's okay. + // Need to actually bind it now - it might only have gotten bound in the init phase. + render_->BindTexture(0, entry->textureName); UpdateSamplingParams(*entry, true); } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 9596b8c769..dbfa828426 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -337,25 +337,31 @@ void GLQueueRunner::LogSteps(const std::vector &steps) { void GLQueueRunner::PerformBlit(const GLRStep &step) { - /* // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing // in ES 2.0 that actually separate them anyway of course, so doesn't matter. - fbo_bind_fb_target(false, dst->handle); - fbo_bind_fb_target(true, src->handle); - if (gl_extensions.GLES3 || gl_extensions.ARB_framebuffer_object) { - glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, aspect, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST); - CHECK_GL_ERROR_IF_DEBUG(); - #if defined(USING_GLES2) && defined(__ANDROID__) // We only support this extension on Android, it's not even available on PC. - return true; - } else if (gl_extensions.NV_framebuffer_blit) { - glBlitFramebufferNV(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, aspect, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST); - CHECK_GL_ERROR_IF_DEBUG(); - #endif // defined(USING_GLES2) && defined(__ANDROID__) - return true; - } else { - return false; - }*/ + fbo_bind_fb_target(false, step.blit.dst->handle); + fbo_bind_fb_target(true, step.blit.src->handle); + int srcX1 = step.blit.srcRect.x; + int srcY1 = step.blit.srcRect.y; + int srcX2 = step.blit.srcRect.x + step.blit.srcRect.w; + int srcY2 = step.blit.srcRect.y + step.blit.srcRect.h; + int dstX1 = step.blit.dstRect.x; + int dstY1 = step.blit.dstRect.y; + int dstX2 = step.blit.dstRect.x + step.blit.dstRect.w; + int dstY2 = step.blit.dstRect.y + step.blit.dstRect.h; + + if (gl_extensions.GLES3 || gl_extensions.ARB_framebuffer_object) { + glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, step.blit.aspectMask, step.blit.filter ? GL_LINEAR : GL_NEAREST); + CHECK_GL_ERROR_IF_DEBUG(); +#if defined(USING_GLES2) && defined(__ANDROID__) // We only support this extension on Android, it's not even available on PC. + } else if (gl_extensions.NV_framebuffer_blit) { + glBlitFramebufferNV(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, step.blit.aspectMask, step.blit.filter ? GL_LINEAR : GL_NEAREST); + CHECK_GL_ERROR_IF_DEBUG(); +#endif // defined(USING_GLES2) && defined(__ANDROID__) + } else { + ERROR_LOG(G3D, "GLQueueRunner: Tried to blit without the capability"); + } } void GLQueueRunner::PerformRenderPass(const GLRStep &step) { @@ -367,6 +373,11 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { PerformBindFramebufferAsRenderTarget(step); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_BLEND); + glDisable(GL_CULL_FACE); glEnable(GL_SCISSOR_TEST); /* @@ -681,7 +692,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glBindVertexArray(0); glDisable(GL_SCISSOR_TEST); glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); + glDisable(GL_CULL_FACE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 6bbae74b09..2ccccd5adb 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -200,13 +200,19 @@ void GLRenderManager::CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLR step->copy.dstPos = dstPos; step->copy.src = src; step->copy.dst = dst; - step->copy.dstPos = dstPos; step->copy.aspectMask = aspectMask; steps_.push_back(step); } void GLRenderManager::BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLRect2D dstRect, int aspectMask, bool filter) { - Crash(); + GLRStep * step = new GLRStep{ GLRStepType::BLIT }; + step->blit.srcRect = srcRect; + step->blit.dstRect = dstRect; + step->blit.src = src; + step->blit.dst = dst; + step->blit.aspectMask = aspectMask; + step->blit.filter = filter; + steps_.push_back(step); } void GLRenderManager::BeginFrame() { @@ -229,6 +235,7 @@ void GLRenderManager::BeginFrame() { // vkWaitForFences(device, 1, &frameData.fence, true, UINT64_MAX); // vkResetFences(device, 1, &frameData.fence); + // glFenceSync(...) // Must be after the fence - this performs deletes. VLOG("PUSH: BeginFrame %d", curFrame); From d5c6786ead15624800fb9d3cee5ba3a0b9a82dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 14 Dec 2017 16:36:05 +0100 Subject: [PATCH 018/291] Fix some texture memory bugs (yeah need to make copies..) --- GPU/GLES/DepalettizeShaderGLES.cpp | 4 +++- GPU/GLES/DrawEngineGLES.cpp | 10 +++++++++- GPU/GLES/FragmentTestCacheGLES.cpp | 7 +++---- GPU/GLES/FragmentTestCacheGLES.h | 1 - 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/GPU/GLES/DepalettizeShaderGLES.cpp b/GPU/GLES/DepalettizeShaderGLES.cpp index 6ea73043a1..63fc9d05bd 100644 --- a/GPU/GLES/DepalettizeShaderGLES.cpp +++ b/GPU/GLES/DepalettizeShaderGLES.cpp @@ -93,7 +93,9 @@ GLRTexture *DepalShaderCacheGLES::GetClutTexture(GEPaletteFormat clutFormat, con GLuint components = dstFmt == GL_UNSIGNED_SHORT_5_6_5 ? GL_RGB : GL_RGBA; GLuint components2 = components; - render_->TextureImage(tex->texture, 0, texturePixels, 1, components, components2, dstFmt, (uint8_t *)rawClut, false); + uint8_t *clutCopy = new uint8_t[1024]; + memcpy(clutCopy, rawClut, 1024); + render_->TextureImage(tex->texture, 0, texturePixels, 1, components, components2, dstFmt, clutCopy, false); tex->lastFrame = gpuStats.numFlips; texCache_[clutId] = tex; diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 92efcc43fb..d6161e4335 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -564,7 +564,15 @@ void DrawEngineGLES::DoFlush() { vai->lastFrame = gpuStats.numFlips; } else { - DecodeVertsToPushBuffer(frameData.pushVertex, &vertexBufferOffset, &vertexBuffer); + if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { + // If software skinning, we've already predecoded into "decoded". So push that content. + size_t size = decodedVerts_ * dec_->GetDecVtxFmt().stride; + u8 *dest = (u8 *)frameData.pushVertex->Push(size, &vertexBufferOffset, &vertexBuffer); + memcpy(dest, decoded, size); + } else { + // Decode directly into the pushbuffer + DecodeVertsToPushBuffer(frameData.pushVertex, &vertexBufferOffset, &vertexBuffer); + } rotateVBO: gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); diff --git a/GPU/GLES/FragmentTestCacheGLES.cpp b/GPU/GLES/FragmentTestCacheGLES.cpp index 4098186d20..0ad098a499 100644 --- a/GPU/GLES/FragmentTestCacheGLES.cpp +++ b/GPU/GLES/FragmentTestCacheGLES.cpp @@ -29,12 +29,10 @@ static const int FRAGTEST_DECIMATION_INTERVAL = 113; FragmentTestCacheGLES::FragmentTestCacheGLES(Draw::DrawContext *draw) { render_ = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - scratchpad_ = new u8[256 * 4]; } FragmentTestCacheGLES::~FragmentTestCacheGLES() { Clear(); - delete [] scratchpad_; } void FragmentTestCacheGLES::BindTestTexture(int slot) { @@ -100,6 +98,7 @@ FragmentTestID FragmentTestCacheGLES::GenerateTestID() const { } GLRTexture *FragmentTestCacheGLES::CreateTestTexture(const GEComparison funcs[4], const u8 refs[4], const u8 masks[4], const bool valid[4]) { + u8 *data = new u8[256 * 4]; // TODO: Might it be better to use GL_ALPHA for simple textures? // TODO: Experiment with 4-bit/etc. textures. @@ -135,12 +134,12 @@ GLRTexture *FragmentTestCacheGLES::CreateTestTexture(const GEComparison funcs[4] break; } } - scratchpad_[color * 4 + i] = res ? 0xFF : 0; + data[color * 4 + i] = res ? 0xFF : 0; } } GLRTexture *tex = render_->CreateTexture(GL_TEXTURE_2D); - render_->TextureImage(tex, 0, 256, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, scratchpad_); + render_->TextureImage(tex, 0, 256, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, data); return tex; } diff --git a/GPU/GLES/FragmentTestCacheGLES.h b/GPU/GLES/FragmentTestCacheGLES.h index 9b6ac1d1be..043b236fe6 100644 --- a/GPU/GLES/FragmentTestCacheGLES.h +++ b/GPU/GLES/FragmentTestCacheGLES.h @@ -79,7 +79,6 @@ private: TextureCacheGLES *textureCache_; std::map cache_; - u8 *scratchpad_ = nullptr; GLRTexture *lastTexture_ = nullptr; int decimationCounter_ = 0; }; From 1241abc887b8d27edacf6d21ca113f6cf2d7281d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 14 Dec 2017 16:54:21 +0100 Subject: [PATCH 019/291] Make sure we set GL_TEXTURE_MAX_LEVEL somewhere. --- GPU/GLES/TextureCacheGLES.cpp | 2 ++ ext/native/thin3d/GLQueueRunner.cpp | 24 +++++++++++++++++------- ext/native/thin3d/GLQueueRunner.h | 5 +++++ ext/native/thin3d/GLRenderManager.h | 7 +++++++ 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index b6cd1cc038..e7bd03f2d5 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -689,6 +689,8 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag entry->SetAlphaStatus(TexCacheEntry::TexStatus(replaced.AlphaStatus())); } + render_->FinalizeTexture(entry->textureName, texMaxLevel); + // This will rebind it, but that's okay. // Need to actually bind it now - it might only have gotten bound in the init phase. render_->BindTexture(0, entry->textureName); diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index dbfa828426..d7870682d0 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -176,17 +176,27 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { { GLRTexture *tex = step.texture_image.texture; CHECK_GL_ERROR_IF_DEBUG(); - if (boundTexture != step.texture_image.texture->texture) { - glBindTexture(step.texture_image.texture->target, step.texture_image.texture->texture); - boundTexture = step.texture_image.texture->texture; + if (boundTexture != tex->texture) { + glBindTexture(tex->target, tex->texture); + boundTexture = tex->texture; } glTexImage2D(tex->target, step.texture_image.level, step.texture_image.internalFormat, step.texture_image.width, step.texture_image.height, 0, step.texture_image.format, step.texture_image.type, step.texture_image.data); delete[] step.texture_image.data; CHECK_GL_ERROR_IF_DEBUG(); - 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, step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(step.texture_finalize.texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(step.texture_finalize.texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(step.texture_finalize.texture->target, GL_TEXTURE_MAG_FILTER, step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(step.texture_finalize.texture->target, GL_TEXTURE_MIN_FILTER, step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST); + break; + } + case GLRInitStepType::TEXTURE_FINALIZE: + { + GLRTexture *tex = step.texture_finalize.texture; + if (boundTexture != tex->texture) { + glBindTexture(tex->target, tex->texture); + boundTexture = tex->texture; + } + glTexParameteri(step.texture_finalize.texture->target, GL_TEXTURE_MAX_LEVEL, step.texture_finalize.maxLevel); break; } default: diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index e4c221b8e1..d155dbe9be 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -178,6 +178,7 @@ enum class GLRInitStepType : uint8_t { TEXTURE_IMAGE, TEXTURE_SUBDATA, + TEXTURE_FINALIZE, BUFFER_SUBDATA, }; @@ -229,6 +230,10 @@ struct GLRInitStep { bool linearFilter; uint8_t *data; // owned, delete[]-d } texture_image; + struct { + GLRTexture *texture; + int maxLevel; + } texture_finalize; }; }; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index c7dcc0b805..04d5d165a8 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -317,6 +317,13 @@ public: initSteps_.push_back(step); } + void FinalizeTexture(GLRTexture *texture, int maxLevels) { + GLRInitStep step{ GLRInitStepType::TEXTURE_FINALIZE }; + step.texture_finalize.texture = texture; + step.texture_finalize.maxLevel = maxLevels; + initSteps_.push_back(step); + } + void BindTexture(int slot, GLRTexture *tex) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::BINDTEXTURE }; From 7c17cb675417626d29b4d7c6370937f114427cf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 14 Dec 2017 17:08:45 +0100 Subject: [PATCH 020/291] Fix showing savestate screenshots (needed mips) --- GPU/GLES/TextureCacheGLES.cpp | 7 ++++--- ext/native/thin3d/GLQueueRunner.cpp | 13 ++++++++----- ext/native/thin3d/GLQueueRunner.h | 1 + ext/native/thin3d/GLRenderManager.h | 9 ++------- ext/native/thin3d/thin3d_gl.cpp | 16 +++++----------- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index e7bd03f2d5..fffdc1da9e 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -651,12 +651,13 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag // Mipmapping only enable when texture scaling disable int texMaxLevel = 0; + bool genMips = false; if (maxLevel > 0 && scaleFactor == 1) { if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) { if (badMipSizes) { // WARN_LOG(G3D, "Bad mipmap for texture sized %dx%dx%d - autogenerating", w, h, (int)format); if (canAutoGen) { - render_->GenerateMipmap(); + genMips = true; } else { texMaxLevel = 0; maxLevel = 0; @@ -671,7 +672,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag // Avoid PowerVR driver bug if (canAutoGen && w > 1 && h > 1 && !(h > w && (gl_extensions.bugs & BUG_PVR_GENMIPMAP_HEIGHT_GREATER))) { // Really! only seems to fail if height > width // NOTICE_LOG(G3D, "Generating mipmap for texture sized %dx%d%d", w, h, (int)format); - render_->GenerateMipmap(); + genMips = true; } else { maxLevel = 0; } @@ -689,7 +690,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag entry->SetAlphaStatus(TexCacheEntry::TexStatus(replaced.AlphaStatus())); } - render_->FinalizeTexture(entry->textureName, texMaxLevel); + render_->FinalizeTexture(entry->textureName, texMaxLevel, genMips); // This will rebind it, but that's okay. // Need to actually bind it now - it might only have gotten bound in the init phase. diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index d7870682d0..7fbff23834 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -183,10 +183,10 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { glTexImage2D(tex->target, step.texture_image.level, step.texture_image.internalFormat, step.texture_image.width, step.texture_image.height, 0, step.texture_image.format, step.texture_image.type, step.texture_image.data); delete[] step.texture_image.data; CHECK_GL_ERROR_IF_DEBUG(); - glTexParameteri(step.texture_finalize.texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(step.texture_finalize.texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(step.texture_finalize.texture->target, GL_TEXTURE_MAG_FILTER, step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST); - glTexParameteri(step.texture_finalize.texture->target, GL_TEXTURE_MIN_FILTER, step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST); break; } case GLRInitStepType::TEXTURE_FINALIZE: @@ -196,7 +196,10 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { glBindTexture(tex->target, tex->texture); boundTexture = tex->texture; } - glTexParameteri(step.texture_finalize.texture->target, GL_TEXTURE_MAX_LEVEL, step.texture_finalize.maxLevel); + glTexParameteri(tex->target, GL_TEXTURE_MAX_LEVEL, step.texture_finalize.maxLevel); + if (step.texture_finalize.genMips) { + glGenerateMipmap(tex->target); + } break; } default: diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index d155dbe9be..b813b77026 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -233,6 +233,7 @@ struct GLRInitStep { struct { GLRTexture *texture; int maxLevel; + bool genMips; } texture_finalize; }; }; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 04d5d165a8..0cab4cb7ca 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -317,10 +317,11 @@ public: initSteps_.push_back(step); } - void FinalizeTexture(GLRTexture *texture, int maxLevels) { + void FinalizeTexture(GLRTexture *texture, int maxLevels, bool genMips) { GLRInitStep step{ GLRInitStepType::TEXTURE_FINALIZE }; step.texture_finalize.texture = texture; step.texture_finalize.maxLevel = maxLevels; + step.texture_finalize.genMips = genMips; initSteps_.push_back(step); } @@ -374,12 +375,6 @@ public: curRenderStep_->commands.push_back(data); } - void GenerateMipmap() { - _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData data{ GLRRenderCommand::GENMIPS }; - curRenderStep_->commands.push_back(data); - } - void SetDepth(bool enabled, bool write, GLenum func) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::DEPTH }; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 5b8ce4b45d..dec2b0b5a3 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -598,8 +598,6 @@ public: render_->BindTexture(stage, tex_); } - void AutoGenMipmaps(); - private: void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data); @@ -638,10 +636,14 @@ OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : } mipLevels_ = desc.generateMips ? desc.mipLevels : level; + bool genMips = false; if ((int)desc.initData.size() < desc.mipLevels && desc.generateMips) { ILOG("Generating mipmaps"); - AutoGenMipmaps(); + // Assumes the texture is bound for editing + genMips = true; + generatedMips_ = true; } + render->FinalizeTexture(tex_, mipLevels_, genMips); } @@ -653,14 +655,6 @@ OpenGLTexture::~OpenGLTexture() { } } -void OpenGLTexture::AutoGenMipmaps() { - if (!generatedMips_) { - // Assumes the texture is bound for editing - render_->GenerateMipmap(); - generatedMips_ = true; - } -} - class OpenGLFramebuffer : public Framebuffer { public: OpenGLFramebuffer(GLRenderManager *render) : render_(render) {} From 970458a0c293f7fbba6520ed9e22156316d09983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 14 Dec 2017 17:55:56 +0100 Subject: [PATCH 021/291] Scissor fix --- ext/native/thin3d/GLQueueRunner.h | 4 ++-- ext/native/thin3d/thin3d_gl.cpp | 8 +------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index b813b77026..1c805f3eed 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -344,7 +344,7 @@ private: GLRFramebuffer *curFB_ = nullptr; - GLuint globalVAO_; + GLuint globalVAO_ = 0; GLint curFramebuffer_ = 0; int curFBWidth_ = 0; @@ -357,7 +357,7 @@ private: GLint readbackBuffer_ = 0; int readbackBufferSize_ = 0; - float maxAnisotropyLevel_; + float maxAnisotropyLevel_ = 0.0f; // Framebuffer state? GLuint currentDrawHandle_ = 0; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index dec2b0b5a3..05aed08ef1 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -395,12 +395,7 @@ public: } void SetScissorRect(int left, int top, int width, int height) override { - int y = top; - if (!curFB_) { - // We render "upside down" to the backbuffer since GL is silly. - y = targetHeight_ - (top + height); - } - renderManager_.SetScissor({ left, y, width, height }); + renderManager_.SetScissor({ left, top, width, height }); } void SetViewports(int count, Viewport *viewports) override { @@ -492,7 +487,6 @@ private: int curVBufferOffsets_[4]{}; OpenGLBuffer *curIBuffer_ = nullptr; int curIBufferOffset_ = 0; - OpenGLFramebuffer *curFB_; // Frames in flight is not such a strict concept as with Vulkan until we start using glBufferStorage and fences. // But might as well have the structure ready, and can't hurt to rotate buffers. From f99fa02ba72146b0803f01371669bdf81aca0bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 14 Dec 2017 17:50:40 +0100 Subject: [PATCH 022/291] Run the depal stuff, seems a bit broken. Add some state filtering. --- CMakeLists.txt | 5 +- GPU/GLES/DepalettizeShaderGLES.cpp | 6 +- GPU/GLES/DepalettizeShaderGLES.h | 2 - GPU/GLES/DrawEngineGLES.cpp | 24 +++++-- GPU/GLES/FramebufferManagerGLES.cpp | 2 +- GPU/GLES/StateMappingGLES.cpp | 9 --- GPU/GLES/TextureCacheGLES.cpp | 101 ++++++++++------------------ GPU/GLES/TextureCacheGLES.h | 2 + ext/native/thin3d/GLQueueRunner.cpp | 38 ++++++++--- ext/native/thin3d/GLQueueRunner.h | 2 +- ext/native/thin3d/GLRenderManager.h | 16 +++-- ext/native/thin3d/thin3d_gl.cpp | 10 +-- 12 files changed, 105 insertions(+), 112 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b60032d8f6..9aeeed988f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -830,7 +830,10 @@ if(ANDROID) set(nativeExtra ${nativeExtra} ${NativeAppSource}) endif() -set(THIN3D_PLATFORMS ext/native/thin3d/thin3d_gl.cpp) +set(THIN3D_PLATFORMS ext/native/thin3d/thin3d_gl.cpp + ext/native/thin3d/GLRenderManager.cpp + ext/native/thin3d/GLQueueRunner.cpp) + set(THIN3D_PLATFORMS ${THIN3D_PLATFORMS} ext/native/thin3d/thin3d_vulkan.cpp ext/native/thin3d/VulkanRenderManager.cpp diff --git a/GPU/GLES/DepalettizeShaderGLES.cpp b/GPU/GLES/DepalettizeShaderGLES.cpp index 63fc9d05bd..95f58f37c6 100644 --- a/GPU/GLES/DepalettizeShaderGLES.cpp +++ b/GPU/GLES/DepalettizeShaderGLES.cpp @@ -167,8 +167,8 @@ DepalShader *DepalShaderCacheGLES::GetDepalettizeShader(uint32_t clutMode, GEBuf queries.push_back({ &depal->u_pal, "pal" }); std::vector initializer; - initializer.push_back({ &depal->u_tex, 0 }); - initializer.push_back({ &depal->u_pal, 3 }); + initializer.push_back({ &depal->u_tex, 0, 0 }); + initializer.push_back({ &depal->u_pal, 0, 3 }); std::vector shaders{ vertexShader_, fragShader }; @@ -177,8 +177,6 @@ DepalShader *DepalShaderCacheGLES::GetDepalettizeShader(uint32_t clutMode, GEBuf depal->program = program; depal->fragShader = fragShader; depal->code = buffer; - depal->a_position = 0; - depal->a_texcoord0 = 1; cache_[id] = depal; delete[] buffer; diff --git a/GPU/GLES/DepalettizeShaderGLES.h b/GPU/GLES/DepalettizeShaderGLES.h index bc3e93facd..6fd9749fec 100644 --- a/GPU/GLES/DepalettizeShaderGLES.h +++ b/GPU/GLES/DepalettizeShaderGLES.h @@ -29,8 +29,6 @@ class DepalShader { public: GLRProgram *program; GLRShader *fragShader; - GLint a_position; - GLint a_texcoord0; GLint u_tex; GLint u_pal; std::string code; diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index d6161e4335..166347016a 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -401,8 +401,14 @@ void DrawEngineGLES::DoFlush() { gpuStats.numFlushes++; gpuStats.numTrackedVertexArrays = (int)vai_.size(); + bool textureNeedsApply = false; + if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) { + textureCache_->SetTexture(); + gstate_c.Clean(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); + textureNeedsApply = true; + } + GEPrimitiveType prim = prevPrim_; - ApplyDrawState(prim); VShaderID vsid; Shader *vshader = shaderManager_->ApplyVertexShader(prim, lastVType_, &vsid); @@ -592,12 +598,17 @@ rotateVBO: gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && ((hasColor && (gstate.materialupdate & 1)) || gstate.getMaterialAmbientA() == 255) && (!gstate.isLightingEnabled() || gstate.getAmbientA() == 255); } + if (textureNeedsApply) + textureCache_->ApplyTexture(); + + // Need to ApplyDrawState after ApplyTexture because depal can launch a render pass and that wrecks the state. + ApplyDrawState(prim); ApplyDrawStateLate(false, 0); LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim); GLRInputLayout *inputLayout = SetupDecFmtForDraw(program, dec_->GetDecVtxFmt()); render_->BindVertexBuffer(vertexBuffer); - render_->BindInputLayout(inputLayout, (void *)(uintptr_t)vertexBufferOffset); + render_->BindInputLayout(inputLayout, vertexBufferOffset); if (useElements) { if (!indexBuffer) { indexBufferOffset = (uint32_t)frameData.pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), &indexBuffer); @@ -653,6 +664,11 @@ rotateVBO: prim, vertexCount, dec_->VertexType(), inds, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(), maxIndex, drawBuffer, numTrans, drawIndexed, ¶ms, &result); + + if (textureNeedsApply) + textureCache_->ApplyTexture(); + + ApplyDrawState(prim); ApplyDrawStateLate(result.setStencil, result.stencilValue); LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim); @@ -666,13 +682,13 @@ rotateVBO: vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(drawBuffer, maxIndex * sizeof(TransformedVertex), &vertexBuffer); indexBufferOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(uint16_t) * numTrans, &indexBuffer); render_->BindVertexBuffer(vertexBuffer); - render_->BindInputLayout(softwareInputLayout_, (void *)(intptr_t)vertexBufferOffset); + render_->BindInputLayout(softwareInputLayout_, vertexBufferOffset); render_->BindIndexBuffer(indexBuffer); render_->DrawIndexed(glprim[prim], numTrans, GL_UNSIGNED_SHORT, (void *)(intptr_t)indexBufferOffset); } else { vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(drawBuffer, numTrans * sizeof(TransformedVertex), &vertexBuffer); render_->BindVertexBuffer(vertexBuffer); - render_->BindInputLayout(softwareInputLayout_, (void *)(intptr_t)vertexBufferOffset); + render_->BindInputLayout(softwareInputLayout_, vertexBufferOffset); render_->Draw(glprim[prim], 0, numTrans); } } else if (result.action == SW_CLEAR) { diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 2f033d736c..76acf62990 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -466,7 +466,7 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float void *dest = drawEngineGL_->GetPushVertexBuffer()->Push(sizeof(verts), &bindOffset, &buffer); memcpy(dest, verts, sizeof(verts)); render_->BindVertexBuffer(buffer); - render_->BindInputLayout(simple2DInputLayout_, (void *)(intptr_t)bindOffset); + render_->BindInputLayout(simple2DInputLayout_, bindOffset); render_->Draw(GL_TRIANGLE_STRIP, 0, 4); } diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index 11b7e79576..932d148656 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -132,11 +132,6 @@ inline void DrawEngineGLES::ResetShaderBlending() { void DrawEngineGLES::ApplyDrawState(int prim) { GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) { - textureCache_->SetTexture(); - gstate_c.Clean(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); - } - if (!gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE)) { // Nothing to do, let's early-out return; @@ -341,10 +336,6 @@ void DrawEngineGLES::ApplyDrawStateLate(bool setStencil, int stencilValue) { fboTexNeedBind_ = false; } - // Apply the texture after the FBO tex, since it might unbind the texture. - // TODO: Could use a separate texture unit to be safer? - textureCache_->ApplyTexture(); - // Apply last, once we know the alpha params of the texture. if (gstate.isAlphaTestEnabled() || gstate.isColorTestEnabled()) { fragmentTestCache_->BindTestTexture(2); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index fffdc1da9e..652082d148 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -53,9 +53,14 @@ TextureCacheGLES::TextureCacheGLES(Draw::DrawContext *draw) SetupTextureDecoder(); nextTexture_ = nullptr; + std::vector entries; + entries.push_back({ 0, 3, GL_FLOAT, GL_FALSE, 20, 0 }); + entries.push_back({ 1, 2, GL_FLOAT, GL_FALSE, 20, 12 }); + shadeInputLayout_ = render_->CreateInputLayout(entries); } TextureCacheGLES::~TextureCacheGLES() { + render_->DeleteInputLayout(shadeInputLayout_); Clear(true); } @@ -65,7 +70,7 @@ void TextureCacheGLES::SetFramebufferManager(FramebufferManagerGLES *fbManager) } void TextureCacheGLES::ReleaseTexture(TexCacheEntry *entry, bool delete_them) { - DEBUG_LOG(G3D, "Deleting texture %i", entry->textureName); + DEBUG_LOG(G3D, "Deleting texture %08x", entry->addr); if (delete_them) { if (entry->textureName) { render_->DeleteTexture(entry->textureName); @@ -322,21 +327,11 @@ void TextureCacheGLES::Unbind() { class TextureShaderApplier { public: struct Pos { - Pos(float x_, float y_, float z_) : x(x_), y(y_), z(z_) { - } - Pos() { - } - float x; float y; float z; }; struct UV { - UV(float u_, float v_) : u(u_), v(v_) { - } - UV() { - } - float u; float v; }; @@ -379,69 +374,45 @@ public: const float top = v1 * invHalfHeight - 1.0f; const float bottom = v2 * invHalfHeight - 1.0f; // Points are: BL, BR, TR, TL. - pos_[0] = Pos(left, bottom, -1.0f); - pos_[1] = Pos(right, bottom, -1.0f); - pos_[2] = Pos(right, top, -1.0f); - pos_[3] = Pos(left, top, -1.0f); + pos_[0] = Pos{ left, bottom, -1.0f }; + pos_[1] = Pos{ right, bottom, -1.0f }; + pos_[2] = Pos{ right, top, -1.0f }; + pos_[3] = Pos{ left, top, -1.0f }; // And also the UVs, same order. const float uvleft = u1 * invWidth; const float uvright = u2 * invWidth; const float uvtop = v1 * invHeight; const float uvbottom = v2 * invHeight; - uv_[0] = UV(uvleft, uvbottom); - uv_[1] = UV(uvright, uvbottom); - uv_[2] = UV(uvright, uvtop); - uv_[3] = UV(uvleft, uvtop); + uv_[0] = UV{ uvleft, uvbottom }; + uv_[1] = UV{ uvright, uvbottom }; + uv_[2] = UV{ uvright, uvtop }; + uv_[3] = UV{ uvleft, uvtop }; } } - void Use(GLRenderManager *render, DrawEngineGLES *transformDraw) { + void Use(GLRenderManager *render, DrawEngineGLES *transformDraw, GLRInputLayout *inputLayout) { render->BindProgram(shader_->program); - - /* - // Restore will rebind all of the state below. - if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { - static const GLubyte indices[4] = { 0, 1, 3, 2 }; - 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); + struct SimpleVertex { + float pos[3]; + float uv[2]; + }; + uint32_t bindOffset; + GLRBuffer *bindBuffer; + SimpleVertex *verts = (SimpleVertex *)transformDraw->GetPushVertexBuffer()->Push(sizeof(SimpleVertex) * 4, &bindOffset, &bindBuffer); + int order[4] = { 0 ,1, 3, 2 }; + for (int i = 0; i < 4; i++) { + memcpy(verts[i].pos, &pos_[order[i]], sizeof(Pos)); + memcpy(verts[i].uv, &uv_[order[i]], sizeof(UV)); } - glEnableVertexAttribArray(shader_->a_position); - glEnableVertexAttribArray(shader_->a_texcoord0); - */ + render->BindVertexBuffer(bindBuffer); + render->BindInputLayout(inputLayout, bindOffset); } - void Shade() { + void Shade(GLRenderManager *render) { static const GLubyte indices[4] = { 0, 1, 3, 2 }; - /* - 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, renderW_, renderH_); - - if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { - glVertexAttribPointer(shader_->a_position, 3, GL_FLOAT, GL_FALSE, 12, 0); - glVertexAttribPointer(shader_->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, (void *)sizeof(pos_)); - glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, 0); - } else { - glVertexAttribPointer(shader_->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos_); - glVertexAttribPointer(shader_->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, uv_); - glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices); - } - glDisableVertexAttribArray(shader_->a_position); - glDisableVertexAttribArray(shader_->a_texcoord0); - - glstate.Restore(); - */ + render->SetViewport(GLRViewport{ 0, 0, (float)renderW_, (float)renderH_, 0.0f, 1.0f }); + render->Draw(GL_TRIANGLE_STRIP, 0, 4); } protected: @@ -469,14 +440,13 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram TextureShaderApplier shaderApply(depal, framebuffer->bufferWidth, framebuffer->bufferHeight, framebuffer->renderWidth, framebuffer->renderHeight); shaderApply.ApplyBounds(gstate_c.vertBounds, gstate_c.curTextureXOffset, gstate_c.curTextureYOffset); - shaderApply.Use(render_, drawEngine_); - - render_->BindTexture(3, clutTexture); + shaderApply.Use(render_, drawEngine_, shadeInputLayout_); framebufferManagerGL_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY); + render_->BindTexture(3, clutTexture); render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); - shaderApply.Shade(); + shaderApply.Shade(render_); draw_->BindFramebufferAsTexture(depalFBO, 0, Draw::FB_COLOR_BIT, 0); @@ -497,6 +467,9 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); InvalidateLastTexture(); + + // Since we started/ended render passes, might need these. + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE); } ReplacedTextureFormat FromGLESFormat(GLenum fmt) { diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index dcefcfb700..2d415c599a 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -101,6 +101,8 @@ private: ShaderManagerGLES *shaderManager_; DrawEngineGLES *drawEngine_; + GLRInputLayout *shadeInputLayout_; + enum { INVALID_TEX = -1 }; }; diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 7fbff23834..0f7288ea3c 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -82,11 +82,9 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { glBindFragDataLocation(program->program, 0, "fragColor0"); } #elif !defined(IOS) - if (gl_extensions.GLES3) { - if (gstate_c.featureFlags & GPU_SUPPORTS_DUALSOURCE_BLEND) { - glBindFragDataLocationIndexedEXT(program->program, 0, 0, "fragColor0"); - glBindFragDataLocationIndexedEXT(program->program, 0, 1, "fragColor1"); - } + if (gl_extensions.GLES3 && step.create_program.support_dual_source) { + glBindFragDataLocationIndexedEXT(program->program, 0, 0, "fragColor0"); + glBindFragDataLocationIndexedEXT(program->program, 0, 1, "fragColor1"); } #endif glLinkProgram(program->program); @@ -413,7 +411,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glActiveTexture(GL_TEXTURE0 + activeTexture); int attrMask = 0; - + int colorMask = -1; + int depthMask = -1; + int depthFunc = -1; // State filtering tracking. GLuint curArrayBuffer = (GLuint)-1; GLuint curElemArrayBuffer = (GLuint)-1; @@ -424,8 +424,14 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { case GLRRenderCommand::DEPTH: if (c.depth.enabled) { glEnable(GL_DEPTH_TEST); - glDepthMask(c.depth.write); - glDepthFunc(c.depth.func); + if (c.depth.write != depthMask) { + glDepthMask(c.depth.write); + depthMask = c.depth.write; + } + if (c.depth.func != depthFunc) { + glDepthFunc(c.depth.func); + depthFunc = c.depth.func; + } } else { glDisable(GL_DEPTH_TEST); } @@ -438,11 +444,15 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } else { glDisable(GL_BLEND); } - glColorMask(c.blend.mask & 1, (c.blend.mask >> 1) & 1, (c.blend.mask >> 2) & 1, (c.blend.mask >> 3) & 1); + if (c.blend.mask != colorMask) { + glColorMask(c.blend.mask & 1, (c.blend.mask >> 1) & 1, (c.blend.mask >> 2) & 1, (c.blend.mask >> 3) & 1); + colorMask = c.blend.mask; + } break; case GLRRenderCommand::CLEAR: glDisable(GL_SCISSOR_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + colorMask = 0xF; if (c.clear.clearMask & GL_COLOR_BUFFER_BIT) { float color[4]; Uint8x4ToFloat4(color, c.clear.clearColor); @@ -485,7 +495,11 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { // TODO: Support FP viewports through glViewportArrays glViewport((GLint)c.viewport.vp.x, (GLint)y, (GLsizei)c.viewport.vp.w, (GLsizei)c.viewport.vp.h); +#if !defined(USING_GLES2) glDepthRange(c.viewport.vp.minZ, c.viewport.vp.maxZ); +#else + glDepthRangef(c.viewport.vp.minZ, c.viewport.vp.maxZ); +#endif break; } case GLRRenderCommand::SCISSOR: @@ -597,8 +611,10 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } case GLRRenderCommand::BINDPROGRAM: { - glUseProgram(c.program.program->program); - curProgram = c.program.program; + if (curProgram != c.program.program) { + glUseProgram(c.program.program->program); + curProgram = c.program.program; + } break; } case GLRRenderCommand::BIND_INPUT_LAYOUT: diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 1c805f3eed..56e2d507eb 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -136,7 +136,7 @@ struct GLRRenderData { } program; struct { GLRInputLayout *inputLayout; - intptr_t offset; + size_t offset; } inputLayout; struct { GLenum wrapS; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 0cab4cb7ca..145e42cc00 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include #include #include "gfx/gl_common.h" @@ -83,8 +85,9 @@ public: }; // Must ONLY be called from GLQueueRunner! + // Also it's pretty slow... int GetUniformLoc(const char *name) { - auto iter = uniformCache_.find(name); + auto iter = uniformCache_.find(std::string(name)); int loc = -1; if (iter != uniformCache_.end()) { loc = iter->second.loc_; @@ -232,6 +235,7 @@ public: step.create_program.program->semantics_ = semantics; step.create_program.program->queries_ = queries; step.create_program.program->initialize_ = initalizers; + step.create_program.support_dual_source = supportDualSource; _assert_msg_(G3D, shaders.size() > 0, "Can't create a program with zero shaders"); for (int i = 0; i < shaders.size(); i++) { step.create_program.shaders[i] = shaders[i]; @@ -288,15 +292,15 @@ public: void BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLRect2D dstRect, int aspectMask, bool filter); // Takes ownership of data if deleteData = true. - void BufferSubdata(GLRBuffer *buffer, int offset, int size, uint8_t *data, bool deleteData = true) { + void BufferSubdata(GLRBuffer *buffer, size_t offset, size_t size, uint8_t *data, bool deleteData = true) { // TODO: Maybe should be a render command instead of an init command? When possible it's better as // an init command, that's for sure. GLRInitStep step{ GLRInitStepType::BUFFER_SUBDATA }; _dbg_assert_(G3D, offset >= 0); _dbg_assert_(G3D, offset <= buffer->size_ - size); step.buffer_subdata.buffer = buffer; - step.buffer_subdata.offset = offset; - step.buffer_subdata.size = size; + step.buffer_subdata.offset = (int)offset; + step.buffer_subdata.size = (int)size; step.buffer_subdata.data = data; step.buffer_subdata.deleteData = deleteData; initSteps_.push_back(step); @@ -366,12 +370,12 @@ public: curRenderStep_->commands.push_back(data); } - void BindInputLayout(GLRInputLayout *inputLayout, const void *offset) { + void BindInputLayout(GLRInputLayout *inputLayout, size_t offset) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); assert(inputLayout); GLRRenderData data{ GLRRenderCommand::BIND_INPUT_LAYOUT }; data.inputLayout.inputLayout = inputLayout; - data.inputLayout.offset = (intptr_t)offset; + data.inputLayout.offset = offset; curRenderStep_->commands.push_back(data); } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 05aed08ef1..76c8d6b6bd 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -1115,7 +1115,6 @@ void OpenGLContext::DrawIndexed(int vertexCount, int offset) { } void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { -#if 1 int stride = curPipeline_->inputLayout->stride; size_t dataSize = stride * vertexCount; @@ -1127,16 +1126,9 @@ void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { ApplySamplers(); renderManager_.BindVertexBuffer(buf); - renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, (void *)offset); + renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, offset); renderManager_.Draw(curPipeline_->prim, 0, vertexCount); -#else - ApplySamplers(); - renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, (void *)vdata); - renderManager_.Draw(curPipeline_->prim, 0, vertexCount); - renderManager_.UnbindInputLayout(curPipeline_->inputLayout->inputLayout_); - -#endif } void OpenGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) { From 84ad7a2dbaf7724ecb40e48943e0b02c4a4577c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 15 Dec 2017 11:05:43 +0100 Subject: [PATCH 023/291] Fix bug, works on Android now. Don't reuse textures. --- GPU/GLES/FramebufferManagerGLES.cpp | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 76acf62990..d4b9263a29 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -98,7 +98,10 @@ void FramebufferManagerGLES::CompileDraw2DProgram() { queries.push_back({ &u_draw2d_tex, "u_tex" }); std::vector initializers; initializers.push_back({ &u_draw2d_tex, 0 }); - draw2dprogram_ = render_->CreateProgram(shaders, {}, queries, initializers, false); + std::vector semantics; + semantics.push_back({ 0, "a_position" }); + semantics.push_back({ 1, "a_texcoord0" }); + draw2dprogram_ = render_->CreateProgram(shaders, semantics, queries, initializers, false); for (auto shader : shaders) render_->DeleteShader(shader); CompilePostShader(); @@ -334,24 +337,15 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma } } - if (drawPixelsTex_ && (drawPixelsTexFormat_ != srcPixelFormat || drawPixelsTexW_ != texWidth || drawPixelsTexH_ != height)) { + if (drawPixelsTex_) { render_->DeleteTexture(drawPixelsTex_); - drawPixelsTex_ = nullptr; } - if (!drawPixelsTex_) { - drawPixelsTex_ = render_->CreateTexture(GL_TEXTURE_2D); - drawPixelsTexW_ = texWidth; - drawPixelsTexH_ = height; + drawPixelsTex_ = render_->CreateTexture(GL_TEXTURE_2D); + drawPixelsTexW_ = texWidth; + drawPixelsTexH_ = height; - render_->BindTexture(0, drawPixelsTex_); - render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); - - // render_->TextureImage(drawPixelsTex_, 0, drawPixelsTexW_, drawPixelsTexH_, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - drawPixelsTexFormat_ = srcPixelFormat; - } else { - render_->BindTexture(0, drawPixelsTex_); - } + drawPixelsTexFormat_ = srcPixelFormat; // TODO: We can just change the texture format and flip some bits around instead of this. // Could share code with the texture cache perhaps. @@ -396,7 +390,8 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma break; } } - render_->TextureImage(drawPixelsTex_, 0, texWidth, height, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, convBuf); + render_->TextureImage(drawPixelsTex_, 0, texWidth, height, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, convBuf, false); + render_->FinalizeTexture(drawPixelsTex_, 0, false); } void FramebufferManagerGLES::SetViewport2D(int x, int y, int w, int h) { From 958078f6032aa2846fa8fdd964218c3e81038c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 19 Dec 2017 12:25:13 +0100 Subject: [PATCH 024/291] GL render manager: Merge BindInputLayout into BindVertexBuffer. --- GPU/GLES/DrawEngineGLES.cpp | 13 ++++--------- GPU/GLES/FramebufferManagerGLES.cpp | 3 +-- GPU/GLES/TextureCacheGLES.cpp | 3 +-- ext/native/thin3d/GLQueueRunner.cpp | 26 +++++++++++++++----------- ext/native/thin3d/GLQueueRunner.h | 5 +++-- ext/native/thin3d/GLRenderManager.h | 21 +++++++-------------- ext/native/thin3d/thin3d_gl.cpp | 29 +++++++++-------------------- 7 files changed, 40 insertions(+), 60 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 166347016a..1cf8e67af5 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -514,7 +514,6 @@ void DrawEngineGLES::DoFlush() { size_t vsz = dec_->GetDecVtxFmt().stride * indexGen.MaxIndex(); vai->vbo = render_->CreateBuffer(GL_ARRAY_BUFFER, vsz, GL_STATIC_DRAW); render_->BufferSubdata(vai->vbo, 0, vsz, decoded); - render_->BindVertexBuffer(vai->vbo); // If there's only been one primitive type, and it's either TRIANGLES, LINES or POINTS, // there is no need for the index buffer we built. We can then use glDrawArrays instead // for a very minor speed boost. @@ -607,16 +606,14 @@ rotateVBO: LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim); GLRInputLayout *inputLayout = SetupDecFmtForDraw(program, dec_->GetDecVtxFmt()); - render_->BindVertexBuffer(vertexBuffer); - render_->BindInputLayout(inputLayout, vertexBufferOffset); + render_->BindVertexBuffer(inputLayout, vertexBuffer, vertexBufferOffset); if (useElements) { if (!indexBuffer) { indexBufferOffset = (uint32_t)frameData.pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), &indexBuffer); render_->BindIndexBuffer(indexBuffer); } if (gstate_c.bezier || gstate_c.spline) - // Instanced rendering for instanced tessellation - ; // glDrawElementsInstanced(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset, numPatches); + render_->DrawIndexed(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset, numPatches); else render_->DrawIndexed(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset); } else { @@ -681,14 +678,12 @@ rotateVBO: if (drawIndexed) { vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(drawBuffer, maxIndex * sizeof(TransformedVertex), &vertexBuffer); indexBufferOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(uint16_t) * numTrans, &indexBuffer); - render_->BindVertexBuffer(vertexBuffer); - render_->BindInputLayout(softwareInputLayout_, vertexBufferOffset); + render_->BindVertexBuffer(softwareInputLayout_, vertexBuffer, vertexBufferOffset); render_->BindIndexBuffer(indexBuffer); render_->DrawIndexed(glprim[prim], numTrans, GL_UNSIGNED_SHORT, (void *)(intptr_t)indexBufferOffset); } else { vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(drawBuffer, numTrans * sizeof(TransformedVertex), &vertexBuffer); - render_->BindVertexBuffer(vertexBuffer); - render_->BindInputLayout(softwareInputLayout_, vertexBufferOffset); + render_->BindVertexBuffer(softwareInputLayout_, vertexBuffer, vertexBufferOffset); render_->Draw(glprim[prim], 0, numTrans); } } else if (result.action == SW_CLEAR) { diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index d4b9263a29..dbfa48c1ad 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -460,8 +460,7 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float GLRBuffer *buffer; void *dest = drawEngineGL_->GetPushVertexBuffer()->Push(sizeof(verts), &bindOffset, &buffer); memcpy(dest, verts, sizeof(verts)); - render_->BindVertexBuffer(buffer); - render_->BindInputLayout(simple2DInputLayout_, bindOffset); + render_->BindVertexBuffer(simple2DInputLayout_, buffer, bindOffset); render_->Draw(GL_TRIANGLE_STRIP, 0, 4); } diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 652082d148..3ff8704bca 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -405,8 +405,7 @@ public: memcpy(verts[i].pos, &pos_[order[i]], sizeof(Pos)); memcpy(verts[i].uv, &uv_[order[i]], sizeof(UV)); } - render->BindVertexBuffer(bindBuffer); - render->BindInputLayout(inputLayout, bindOffset); + render->BindVertexBuffer(inputLayout, bindBuffer, bindOffset); } void Shade(GLRenderManager *render) { diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 0f7288ea3c..63343f6883 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -617,12 +617,17 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } break; } - case GLRRenderCommand::BIND_INPUT_LAYOUT: + case GLRRenderCommand::BIND_VERTEX_BUFFER: { - GLRInputLayout *layout = c.inputLayout.inputLayout; - int enable, disable; - enable = layout->semanticsMask_ & ~attrMask; - disable = (~layout->semanticsMask_) & attrMask; + // TODO: Add fast path for glBindVertexBuffer + GLRInputLayout *layout = c.bindVertexBuffer.inputLayout; + GLuint buf = c.bindVertexBuffer.buffer ? c.bindVertexBuffer.buffer->buffer : 0; + if (buf != curArrayBuffer) { + glBindBuffer(GL_ARRAY_BUFFER, buf); + curArrayBuffer = buf; + } + int enable = layout->semanticsMask_ & ~attrMask; + int disable = (~layout->semanticsMask_) & attrMask; for (int i = 0; i < 7; i++) { // SEM_MAX if (enable & (1 << i)) { glEnableVertexAttribArray(i); @@ -634,18 +639,14 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { attrMask = layout->semanticsMask_; for (int i = 0; i < layout->entries.size(); i++) { auto &entry = layout->entries[i]; - glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.inputLayout.offset + entry.offset)); + glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.bindVertexBuffer.offset + entry.offset)); } break; } case GLRRenderCommand::BIND_BUFFER: { if (c.bind_buffer.target == GL_ARRAY_BUFFER) { - GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0; - if (buf != curArrayBuffer) { - glBindBuffer(GL_ARRAY_BUFFER, buf); - curArrayBuffer = buf; - } + Crash(); } else if (c.bind_buffer.target == GL_ELEMENT_ARRAY_BUFFER) { GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0; if (buf != curElemArrayBuffer) { @@ -660,6 +661,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } case GLRRenderCommand::GENMIPS: // TODO: Should we include the texture handle in the command? + // Also, should this not be an init command? glGenerateMipmap(GL_TEXTURE_2D); break; case GLRRenderCommand::DRAW: @@ -668,6 +670,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { case GLRRenderCommand::DRAW_INDEXED: if (c.drawIndexed.instances == 1) { glDrawElements(c.drawIndexed.mode, c.drawIndexed.count, c.drawIndexed.indexType, c.drawIndexed.indices); + } else { + glDrawElementsInstanced(c.drawIndexed.mode, c.drawIndexed.count, c.drawIndexed.indexType, c.drawIndexed.indices, c.drawIndexed.instances); } break; case GLRRenderCommand::TEXTURESAMPLER: diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 56e2d507eb..16a97f5be0 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -45,7 +45,7 @@ enum class GLRRenderCommand : uint8_t { BINDPROGRAM, BINDTEXTURE, BIND_FB_TEXTURE, - BIND_INPUT_LAYOUT, + BIND_VERTEX_BUFFER, BIND_BUFFER, GENMIPS, DRAW, @@ -136,8 +136,9 @@ struct GLRRenderData { } program; struct { GLRInputLayout *inputLayout; + GLRBuffer *buffer; size_t offset; - } inputLayout; + } bindVertexBuffer; struct { GLenum wrapS; GLenum wrapT; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 145e42cc00..de559fcc31 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -346,14 +346,6 @@ public: curRenderStep_->commands.push_back(data); } - void BindVertexBuffer(GLRBuffer *buffer) { // Want to support an offset but can't in ES 2.0. We supply an offset when binding the buffers instead. - _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData data{ GLRRenderCommand::BIND_BUFFER }; - data.bind_buffer.buffer = buffer; - data.bind_buffer.target = GL_ARRAY_BUFFER; - curRenderStep_->commands.push_back(data); - } - void BindPixelPackBuffer(GLRBuffer *buffer) { // Want to support an offset but can't in ES 2.0. We supply an offset when binding the buffers instead. _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::BIND_BUFFER }; @@ -370,12 +362,13 @@ public: curRenderStep_->commands.push_back(data); } - void BindInputLayout(GLRInputLayout *inputLayout, size_t offset) { + void BindVertexBuffer(GLRInputLayout *inputLayout, GLRBuffer *buffer, size_t offset) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); assert(inputLayout); - GLRRenderData data{ GLRRenderCommand::BIND_INPUT_LAYOUT }; - data.inputLayout.inputLayout = inputLayout; - data.inputLayout.offset = offset; + GLRRenderData data{ GLRRenderCommand::BIND_VERTEX_BUFFER }; + data.bindVertexBuffer.inputLayout = inputLayout; + data.bindVertexBuffer.offset = offset; + data.bindVertexBuffer.buffer = buffer; curRenderStep_->commands.push_back(data); } @@ -579,13 +572,13 @@ public: curRenderStep_->render.numDraws++; } - void DrawIndexed(GLenum mode, int count, GLenum indexType, void *indices) { + void DrawIndexed(GLenum mode, int count, GLenum indexType, void *indices, int instances = 1) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::DRAW_INDEXED }; data.drawIndexed.mode = mode; data.drawIndexed.count = count; data.drawIndexed.indexType = indexType; - data.drawIndexed.instances = 1; + data.drawIndexed.instances = instances; data.drawIndexed.indices = indices; curRenderStep_->commands.push_back(data); curRenderStep_->render.numDraws++; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 76c8d6b6bd..f65b765e48 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -940,13 +940,6 @@ public: render_->DeleteBuffer(buffer_); } - void Bind(int offset) { - Crash(); - // render_->BindBuffer(buffer_); - // TODO: Can't support offset using ES 2.0 - // glBindBuffer(target_, buffer_); - } - GLRenderManager *render_; GLRBuffer *buffer_; GLuint target_; @@ -962,7 +955,6 @@ Buffer *OpenGLContext::CreateBuffer(size_t size, uint32_t usageFlags) { void OpenGLContext::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) { OpenGLBuffer *buf = (OpenGLBuffer *)buffer; - buf->Bind(0); if (size + offset > buf->totalSize_) { Crash(); } @@ -970,6 +962,7 @@ void OpenGLContext::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t off uint8_t *dataCopy = new uint8_t[size]; memcpy(dataCopy, data, size); // if (flags & UPDATE_DISCARD) we could try to orphan the buffer using glBufferData. + // But we're much better off using separate buffers per FrameData... renderManager_.BufferSubdata(buf->buffer_, offset, size, dataCopy); } @@ -1097,21 +1090,19 @@ void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) { } void OpenGLContext::Draw(int vertexCount, int offset) { - curVBuffers_[0]->Bind(curVBufferOffsets_[0]); - renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, 0); + _dbg_assert_msg_(G3D, curVBuffers_[0], "Can't call Draw without a vertex buffer"); ApplySamplers(); - + renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]); renderManager_.Draw(curPipeline_->prim, offset, vertexCount); } void OpenGLContext::DrawIndexed(int vertexCount, int offset) { - curVBuffers_[0]->Bind(curVBufferOffsets_[0]); - renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, 0); + _dbg_assert_msg_(G3D, curVBuffers_[0], "Can't call DrawIndexed without a vertex buffer"); + _dbg_assert_msg_(G3D, curIBuffer_, "Can't call DrawIndexed without an index buffer"); ApplySamplers(); - // Note: ibuf binding is stored in the VAO, so call this after binding the fmt. - curIBuffer_->Bind(curIBufferOffset_); - - renderManager_.DrawIndexed(curPipeline_->prim, vertexCount, GL_UNSIGNED_INT, (void *)(intptr_t)offset); + renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]); + renderManager_.BindIndexBuffer(curIBuffer_->buffer_); + renderManager_.DrawIndexed(curPipeline_->prim, vertexCount, GL_UNSIGNED_INT, (void *)(intptr_t)curIBufferOffset_); } void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { @@ -1125,9 +1116,7 @@ void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { ApplySamplers(); - renderManager_.BindVertexBuffer(buf); - renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, offset); - + renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, buf, offset); renderManager_.Draw(curPipeline_->prim, 0, vertexCount); } From 0a413a18a7fa63247de4250f1c96f47b07349733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 19 Dec 2017 12:49:48 +0100 Subject: [PATCH 025/291] GL render manager: Add some more dirty tracking. --- ext/native/thin3d/GLQueueRunner.cpp | 73 ++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 63343f6883..1d9f9ca108 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -389,6 +389,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); + glDisable(GL_DITHER); glEnable(GL_SCISSOR_TEST); /* @@ -410,20 +411,29 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { int activeTexture = 0; glActiveTexture(GL_TEXTURE0 + activeTexture); + // State filtering tracking. int attrMask = 0; int colorMask = -1; int depthMask = -1; int depthFunc = -1; - // State filtering tracking. GLuint curArrayBuffer = (GLuint)-1; GLuint curElemArrayBuffer = (GLuint)-1; + bool depthEnabled = false; + bool blendEnabled = false; + bool cullEnabled = false; + bool ditherEnabled = false; + GLuint blendEqColor = (GLuint)-1; + GLuint blendEqAlpha = (GLuint)-1; auto &commands = step.commands; for (const auto &c : commands) { switch (c.cmd) { case GLRRenderCommand::DEPTH: if (c.depth.enabled) { - glEnable(GL_DEPTH_TEST); + if (!depthEnabled) { + glEnable(GL_DEPTH_TEST); + depthEnabled = true; + } if (c.depth.write != depthMask) { glDepthMask(c.depth.write); depthMask = c.depth.write; @@ -432,17 +442,38 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glDepthFunc(c.depth.func); depthFunc = c.depth.func; } - } else { + } else if (!c.depth.enabled && depthEnabled) { glDisable(GL_DEPTH_TEST); + depthEnabled = false; } break; + case GLRRenderCommand::STENCILFUNC: + if (c.stencilFunc.enabled) { + glEnable(GL_STENCIL_TEST); + glStencilFunc(c.stencilFunc.func, c.stencilFunc.ref, c.stencilFunc.compareMask); + } else { + glDisable(GL_STENCIL_TEST); + } + break; + case GLRRenderCommand::STENCILOP: + glStencilOp(c.stencilOp.sFail, c.stencilOp.zFail, c.stencilOp.pass); + glStencilMask(c.stencilOp.writeMask); + break; case GLRRenderCommand::BLEND: if (c.blend.enabled) { - glEnable(GL_BLEND); - glBlendEquationSeparate(c.blend.funcColor, c.blend.funcAlpha); + if (!blendEnabled) { + glEnable(GL_BLEND); + blendEnabled = true; + } + if (blendEqColor != c.blend.funcColor || blendEqAlpha != c.blend.funcAlpha) { + glBlendEquationSeparate(c.blend.funcColor, c.blend.funcAlpha); + blendEqColor = c.blend.funcColor; + blendEqAlpha = c.blend.funcAlpha; + } glBlendFuncSeparate(c.blend.srcColor, c.blend.dstColor, c.blend.srcAlpha, c.blend.dstAlpha); - } else { + } else if (!c.blend.enabled && blendEnabled) { glDisable(GL_BLEND); + blendEnabled = false; } if (c.blend.mask != colorMask) { glColorMask(c.blend.mask & 1, (c.blend.mask >> 1) & 1, (c.blend.mask >> 2) & 1, (c.blend.mask >> 3) & 1); @@ -569,18 +600,6 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } break; } - case GLRRenderCommand::STENCILFUNC: - if (c.stencilFunc.enabled) { - glEnable(GL_STENCIL_TEST); - glStencilFunc(c.stencilFunc.func, c.stencilFunc.ref, c.stencilFunc.compareMask); - } else { - glDisable(GL_STENCIL_TEST); - } - break; - case GLRRenderCommand::STENCILOP: - glStencilOp(c.stencilOp.sFail, c.stencilOp.zFail, c.stencilOp.pass); - glStencilMask(c.stencilOp.writeMask); - break; case GLRRenderCommand::BINDTEXTURE: { GLint slot = c.texture.slot; @@ -692,16 +711,24 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { break; case GLRRenderCommand::RASTER: if (c.raster.cullEnable) { - glEnable(GL_CULL_FACE); + if (!cullEnabled) { + glEnable(GL_CULL_FACE); + cullEnabled = true; + } glFrontFace(c.raster.frontFace); glCullFace(c.raster.cullFace); - } else { + } else if (!c.raster.cullEnable && cullEnabled) { glDisable(GL_CULL_FACE); + cullEnabled = false; } if (c.raster.ditherEnable) { - glEnable(GL_DITHER); - } else { + if (!ditherEnabled) { + glEnable(GL_DITHER); + ditherEnabled = true; + } + } else if (!c.raster.ditherEnable && ditherEnabled) { glDisable(GL_DITHER); + ditherEnabled = false; } break; default: @@ -858,7 +885,7 @@ void GLQueueRunner::fbo_ext_create(const GLRInitStep &step) { glGenRenderbuffersEXT(1, &fbo->z_stencil_buffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, fbo->width, fbo->height); - //glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, width, height); + // glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, width, height); // Bind it all together glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); From 2b12776137fbf36840e081eb48a10b1709f75c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 19 Dec 2017 12:59:57 +0100 Subject: [PATCH 026/291] Remove viewport flipping where it's not needed --- GPU/GLES/StateMappingGLES.cpp | 7 ------- ext/native/thin3d/GLQueueRunner.cpp | 4 ++-- ext/native/thin3d/GLQueueRunner.h | 1 - 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index 932d148656..1c8f52911d 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -298,14 +298,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) { framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); - if (!useBufferedRendering) { - vpAndScissor.scissorY = PSP_CoreParameter().pixelHeight - vpAndScissor.scissorH - vpAndScissor.scissorY; - } renderManager->SetScissor(GLRect2D{ vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH }); - - if (!useBufferedRendering) { - vpAndScissor.viewportY = PSP_CoreParameter().pixelHeight - vpAndScissor.viewportH - vpAndScissor.viewportY; - } renderManager->SetViewport({ vpAndScissor.viewportX, vpAndScissor.viewportY, vpAndScissor.viewportW, vpAndScissor.viewportH, diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 1d9f9ca108..c1230dbb54 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -521,7 +521,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { case GLRRenderCommand::VIEWPORT: { float y = c.viewport.vp.y; - if (!curFramebuffer_) + if (!curFB_) y = curFBHeight_ - y - c.viewport.vp.h; // TODO: Support FP viewports through glViewportArrays @@ -536,7 +536,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { case GLRRenderCommand::SCISSOR: { int y = c.scissor.rc.y; - if (!curFramebuffer_) + if (!curFB_) y = curFBHeight_ - y - c.scissor.rc.h; glScissor(c.scissor.rc.x, y, c.scissor.rc.w, c.scissor.rc.h); break; diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 16a97f5be0..a2a4ae9dab 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -347,7 +347,6 @@ private: GLuint globalVAO_ = 0; - GLint curFramebuffer_ = 0; int curFBWidth_ = 0; int curFBHeight_ = 0; int targetWidth_ = 0; From 49c3cb83fe25396f43da88b92112242b845fe81c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 19 Dec 2017 14:35:24 +0100 Subject: [PATCH 027/291] GL render manager: Simple implementation of synchronous framebuffer readbacks. --- CMakeLists.txt | 6 +- ext/native/Android.mk | 3 + ext/native/native.vcxproj | 2 + ext/native/native.vcxproj.filters | 6 ++ ext/native/thin3d/DataFormatGL.cpp | 90 ++++++++++++++++++ ext/native/thin3d/DataFormatGL.h | 10 ++ ext/native/thin3d/GLQueueRunner.cpp | 54 ++++++++++- ext/native/thin3d/GLQueueRunner.h | 3 +- ext/native/thin3d/GLRenderManager.cpp | 67 +++++++++++++- ext/native/thin3d/thin3d_gl.cpp | 126 ++------------------------ 10 files changed, 246 insertions(+), 121 deletions(-) create mode 100644 ext/native/thin3d/DataFormatGL.cpp create mode 100644 ext/native/thin3d/DataFormatGL.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9aeeed988f..ee283b1079 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -832,7 +832,11 @@ endif() set(THIN3D_PLATFORMS ext/native/thin3d/thin3d_gl.cpp ext/native/thin3d/GLRenderManager.cpp - ext/native/thin3d/GLQueueRunner.cpp) + ext/native/thin3d/GLRenderManager.h + ext/native/thin3d/GLQueueRunner.cpp + ext/native/thin3d/GLQueueRunner.h + ext/native/thin3d/DataFormatGL.cpp + ext/native/thin3d/DataFormatGL.h) set(THIN3D_PLATFORMS ${THIN3D_PLATFORMS} ext/native/thin3d/thin3d_vulkan.cpp diff --git a/ext/native/Android.mk b/ext/native/Android.mk index fd0e69181f..78a75db9d4 100644 --- a/ext/native/Android.mk +++ b/ext/native/Android.mk @@ -83,8 +83,11 @@ LOCAL_SRC_FILES :=\ thin3d/thin3d.cpp \ thin3d/thin3d_gl.cpp \ thin3d/thin3d_vulkan.cpp \ + thin3d/GLRenderManager.cpp \ + thin3d/GLQueueRunner.cpp \ thin3d/VulkanRenderManager.cpp \ thin3d/VulkanQueueRunner.cpp \ + thin3d/DataFormatGL.cpp \ ui/view.cpp \ ui/viewgroup.cpp \ ui/ui.cpp \ diff --git a/ext/native/native.vcxproj b/ext/native/native.vcxproj index a9929e396a..ebb1517ea2 100644 --- a/ext/native/native.vcxproj +++ b/ext/native/native.vcxproj @@ -240,6 +240,7 @@ + @@ -699,6 +700,7 @@ + diff --git a/ext/native/native.vcxproj.filters b/ext/native/native.vcxproj.filters index 7336d62265..e0507e183a 100644 --- a/ext/native/native.vcxproj.filters +++ b/ext/native/native.vcxproj.filters @@ -335,6 +335,9 @@ thin3d + + thin3d + @@ -805,6 +808,9 @@ thin3d + + thin3d + diff --git a/ext/native/thin3d/DataFormatGL.cpp b/ext/native/thin3d/DataFormatGL.cpp new file mode 100644 index 0000000000..389d6046e8 --- /dev/null +++ b/ext/native/thin3d/DataFormatGL.cpp @@ -0,0 +1,90 @@ +#include "thin3d/DataFormatGL.h" +#include "base/logging.h" +#include "Common/Log.h" + +namespace Draw { + +// TODO: Also output storage format (GL_RGBA8 etc) for modern GL usage. +bool Thin3DFormatToFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuint &format, GLuint &type, int &alignment) { + alignment = 4; + switch (fmt) { + case DataFormat::R8G8B8A8_UNORM: + internalFormat = GL_RGBA; + format = GL_RGBA; + type = GL_UNSIGNED_BYTE; + break; + + case DataFormat::D32F: + internalFormat = GL_DEPTH_COMPONENT; + format = GL_DEPTH_COMPONENT; + type = GL_FLOAT; + break; + +#ifndef USING_GLES2 + case DataFormat::S8: + internalFormat = GL_STENCIL_INDEX; + format = GL_STENCIL_INDEX; + type = GL_UNSIGNED_BYTE; + alignment = 1; + break; +#endif + + case DataFormat::R8G8B8_UNORM: + internalFormat = GL_RGB; + format = GL_RGB; + type = GL_UNSIGNED_BYTE; + alignment = 1; + break; + + case DataFormat::B4G4R4A4_UNORM_PACK16: + internalFormat = GL_RGBA; + format = GL_RGBA; + type = GL_UNSIGNED_SHORT_4_4_4_4; + alignment = 2; + break; + + case DataFormat::B5G6R5_UNORM_PACK16: + internalFormat = GL_RGB; + format = GL_RGB; + type = GL_UNSIGNED_SHORT_5_6_5; + alignment = 2; + break; + + case DataFormat::B5G5R5A1_UNORM_PACK16: + internalFormat = GL_RGBA; + format = GL_RGBA; + type = GL_UNSIGNED_SHORT_5_5_5_1; + alignment = 2; + break; + +#ifndef USING_GLES2 + case DataFormat::A4R4G4B4_UNORM_PACK16: + internalFormat = GL_RGBA; + format = GL_RGBA; + type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + alignment = 2; + break; + + case DataFormat::R5G6B5_UNORM_PACK16: + internalFormat = GL_RGB; + format = GL_RGB; + type = GL_UNSIGNED_SHORT_5_6_5_REV; + alignment = 2; + break; + + case DataFormat::A1R5G5B5_UNORM_PACK16: + internalFormat = GL_RGBA; + format = GL_RGBA; + type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + alignment = 2; + break; +#endif + + default: + _assert_msg_(G3D, false, "Thin3d GL: Unsupported texture format %d", (int)fmt); + return false; + } + return true; +} + +} \ No newline at end of file diff --git a/ext/native/thin3d/DataFormatGL.h b/ext/native/thin3d/DataFormatGL.h new file mode 100644 index 0000000000..28b48f60ff --- /dev/null +++ b/ext/native/thin3d/DataFormatGL.h @@ -0,0 +1,10 @@ +#pragma once + +#include "gfx/gl_common.h" +#include "thin3d/DataFormat.h" + +namespace Draw { + +bool Thin3DFormatToFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuint &format, GLuint &type, int &alignment); + +} diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index c1230dbb54..21d78f757d 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -1,5 +1,6 @@ #include "GLQueueRunner.h" #include "GLRenderManager.h" +#include "DataFormatGL.h" #include "base/logging.h" #include "gfx/gl_common.h" #include "gfx/gl_debug_log.h" @@ -789,6 +790,10 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) { */ break; } + + _dbg_assert_(G3D, srcTex); + _dbg_assert_(G3D, dstTex); + #if defined(USING_GLES2) #ifndef IOS glCopyImageSubDataOES( @@ -813,7 +818,49 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) { } void GLQueueRunner::PerformReadback(const GLRStep &pass) { + GLRFramebuffer *fb = pass.readback.src; + fbo_bind_fb_target(true, fb ? fb->handle : 0); + + // Reads from the "bound for read" framebuffer. + if (gl_extensions.GLES3 || !gl_extensions.IsGLES) + glReadBuffer(GL_COLOR_ATTACHMENT0); + + CHECK_GL_ERROR_IF_DEBUG(); + + GLuint internalFormat; + GLuint format; + GLuint type; + int alignment; + if (!Draw::Thin3DFormatToFormatAndType(pass.readback.dstFormat, internalFormat, format, type, alignment)) { + assert(false); + } + int pixelStride = pass.readback.srcRect.w; + // Apply the correct alignment. + glPixelStorei(GL_PACK_ALIGNMENT, alignment); + if (!gl_extensions.IsGLES || gl_extensions.GLES3) { + // Some drivers seem to require we specify this. See #8254. + glPixelStorei(GL_PACK_ROW_LENGTH, pixelStride); + } + + GLRect2D rect = pass.readback.srcRect; + + int size = alignment * rect.w * rect.h; + if (size > readbackBufferSize_) { + delete[] readbackBuffer_; + readbackBuffer_ = new uint8_t[size]; + readbackBufferSize_ = size; + } + + glReadPixels(rect.x, rect.y, rect.w, rect.h, format, type, readbackBuffer_); + + #ifdef DEBUG_READ_PIXELS + LogReadPixelsError(glGetError()); + #endif + if (!gl_extensions.IsGLES || gl_extensions.GLES3) { + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + } + CHECK_GL_ERROR_IF_DEBUG(); } void GLQueueRunner::PerformReadbackImage(const GLRStep &pass) { @@ -841,7 +888,12 @@ void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) { } void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { - + // TODO: Maybe move data format conversion here, and always read back 8888. Drivers + // don't usually provide very optimized implementations. + int bpp = Draw::DataFormatSizeInBytes(destFormat); + for (int y = 0; y < height; y++) { + memcpy(pixels + y * pixelStride * bpp, readbackBuffer_ + y * width * bpp, pixelStride * bpp); + } } GLuint GLQueueRunner::AllocTextureName() { diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index a2a4ae9dab..6bea398557 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -289,6 +289,7 @@ struct GLRStep { int aspectMask; GLRFramebuffer *src; GLRect2D srcRect; + Draw::DataFormat dstFormat; } readback; struct { GLint texture; @@ -354,7 +355,7 @@ private: // Readback buffer. Currently we only support synchronous readback, so we only really need one. // We size it generously. - GLint readbackBuffer_ = 0; + uint8_t *readbackBuffer_ = nullptr; int readbackBufferSize_ = 0; float maxAnisotropyLevel_ = 0.0f; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 2ccccd5adb..27b9fe6ad3 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -215,6 +215,33 @@ void GLRenderManager::BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLR steps_.push_back(step); } +bool GLRenderManager::CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride) { + GLRStep *step = new GLRStep{ GLRStepType::READBACK }; + step->readback.src = src; + step->readback.srcRect = { x, y, w, h }; + step->readback.aspectMask = aspectBits; + step->readback.dstFormat = destFormat; + steps_.push_back(step); + + curRenderStep_ = nullptr; + FlushSync(); + + Draw::DataFormat srcFormat; + if (aspectBits & GL_COLOR_BUFFER_BIT) { + srcFormat = Draw::DataFormat::R8G8B8A8_UNORM; + } else if (aspectBits & GL_STENCIL_BUFFER_BIT) { + // Copies from stencil are always S8. + srcFormat = Draw::DataFormat::S8; + } else if (aspectBits & GL_DEPTH_BUFFER_BIT) { + // TODO: Do this properly. + srcFormat = Draw::DataFormat::D24_S8; + } else { + _assert_(false); + } + queueRunner_.CopyReadbackBuffer(w, h, srcFormat, destFormat, pixelStride, pixels); + return true; +} + void GLRenderManager::BeginFrame() { VLOG("BeginFrame"); @@ -255,14 +282,18 @@ void GLRenderManager::Finish() { FrameData &frameData = frameData_[curFrame]; if (!useThread_) { frameData.steps = std::move(steps_); + steps_.clear(); frameData.initSteps = std::move(initSteps_); + initSteps_.clear(); frameData.type = GLRRunType::END; Run(curFrame); } else { std::unique_lock lock(frameData.pull_mutex); VLOG("PUSH: Frame[%d].readyForRun = true", curFrame); frameData.steps = std::move(steps_); + steps_.clear(); frameData.initSteps = std::move(initSteps_); + initSteps_.clear(); frameData.readyForRun = true; frameData.type = GLRRunType::END; frameData.pull_condVar.notify_all(); @@ -340,6 +371,41 @@ void GLRenderManager::Run(int frame) { VLOG("PULL: Finished running frame %d", frame); } +void GLRenderManager::FlushSync() { + // TODO: Reset curRenderStep_? + int curFrame = curFrame_; + FrameData &frameData = frameData_[curFrame]; + if (!useThread_) { + frameData.initSteps = std::move(initSteps_); + initSteps_.clear(); + frameData.steps = std::move(steps_); + steps_.clear(); + frameData.type = GLRRunType::SYNC; + Run(curFrame); + } else { + std::unique_lock lock(frameData.pull_mutex); + VLOG("PUSH: Frame[%d].readyForRun = true (sync)", curFrame); + frameData.initSteps = std::move(initSteps_); + initSteps_.clear(); + frameData.steps = std::move(steps_); + steps_.clear(); + frameData.readyForRun = true; + assert(frameData.readyForFence == false); + frameData.type = GLRRunType::SYNC; + frameData.pull_condVar.notify_all(); + } + + if (useThread_) { + std::unique_lock lock(frameData.push_mutex); + // Wait for the flush to be hit, since we're syncing. + while (!frameData.readyForFence) { + VLOG("PUSH: Waiting for frame[%d].readyForFence = 1 (sync)", curFrame); + frameData.push_condVar.wait(lock); + } + frameData.readyForFence = false; + } +} + void GLRenderManager::EndSyncFrame(int frame) { FrameData &frameData = frameData_[frame]; Submit(frame, false); @@ -347,7 +413,6 @@ void GLRenderManager::EndSyncFrame(int frame) { // This is brutal! Should probably wait for a fence instead, not that it'll matter much since we'll // still stall everything. glFinish(); - // vkDeviceWaitIdle(vulkan_->GetDevice()); // At this point we can resume filling the command buffers for the current frame since // we know the device is idle - and thus all previously enqueued command buffers have been processed. diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index f65b765e48..194d065ec0 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -9,6 +9,7 @@ #include "math/dataconv.h" #include "math/lin/matrix4x4.h" #include "thin3d/thin3d.h" +#include "thin3d/DataFormatGL.h" #include "gfx/gl_common.h" #include "gfx/gl_debug_log.h" #include "gfx_es2/gpu_features.h" @@ -662,90 +663,6 @@ public: FBColorDepth colorDepth; }; - -// TODO: Also output storage format (GL_RGBA8 etc) for modern GL usage. -static bool Thin3DFormatToFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuint &format, GLuint &type, int &alignment) { - alignment = 4; - switch (fmt) { - case DataFormat::R8G8B8A8_UNORM: - internalFormat = GL_RGBA; - format = GL_RGBA; - type = GL_UNSIGNED_BYTE; - break; - - case DataFormat::D32F: - internalFormat = GL_DEPTH_COMPONENT; - format = GL_DEPTH_COMPONENT; - type = GL_FLOAT; - break; - -#ifndef USING_GLES2 - case DataFormat::S8: - internalFormat = GL_STENCIL_INDEX; - format = GL_STENCIL_INDEX; - type = GL_UNSIGNED_BYTE; - alignment = 1; - break; -#endif - - case DataFormat::R8G8B8_UNORM: - internalFormat = GL_RGB; - format = GL_RGB; - type = GL_UNSIGNED_BYTE; - alignment = 1; - break; - - case DataFormat::B4G4R4A4_UNORM_PACK16: - internalFormat = GL_RGBA; - format = GL_RGBA; - type = GL_UNSIGNED_SHORT_4_4_4_4; - alignment = 2; - break; - - case DataFormat::B5G6R5_UNORM_PACK16: - internalFormat = GL_RGB; - format = GL_RGB; - type = GL_UNSIGNED_SHORT_5_6_5; - alignment = 2; - break; - - case DataFormat::B5G5R5A1_UNORM_PACK16: - internalFormat = GL_RGBA; - format = GL_RGBA; - type = GL_UNSIGNED_SHORT_5_5_5_1; - alignment = 2; - break; - -#ifndef USING_GLES2 - case DataFormat::A4R4G4B4_UNORM_PACK16: - internalFormat = GL_RGBA; - format = GL_RGBA; - type = GL_UNSIGNED_SHORT_4_4_4_4_REV; - alignment = 2; - break; - - case DataFormat::R5G6B5_UNORM_PACK16: - internalFormat = GL_RGB; - format = GL_RGB; - type = GL_UNSIGNED_SHORT_5_6_5_REV; - alignment = 2; - break; - - case DataFormat::A1R5G5B5_UNORM_PACK16: - internalFormat = GL_RGBA; - format = GL_RGBA; - type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - alignment = 2; - break; -#endif - - default: - ELOG("Thin3d GL: Unsupported texture format %d", (int)fmt); - return false; - } - return true; -} - void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) { if (width != width_ || height != height_ || depth != depth_) { // When switching to texStorage we need to handle this correctly. @@ -811,39 +728,14 @@ static void LogReadPixelsError(GLenum error) { bool OpenGLContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat dataFormat, void *pixels, int pixelStride) { OpenGLFramebuffer *fb = (OpenGLFramebuffer *)src; - /* - fbo_bind_fb_target(true, fb ? fb->handle : 0); - - // Reads from the "bound for read" framebuffer. - if (gl_extensions.GLES3 || !gl_extensions.IsGLES) - glReadBuffer(GL_COLOR_ATTACHMENT0); - - CHECK_GL_ERROR_IF_DEBUG(); - - GLuint internalFormat; - GLuint format; - GLuint type; - int alignment; - if (!Thin3DFormatToFormatAndType(dataFormat, internalFormat, format, type, alignment)) { - assert(false); - } - // Apply the correct alignment. - glPixelStorei(GL_PACK_ALIGNMENT, alignment); - if (!gl_extensions.IsGLES || gl_extensions.GLES3) { - // Even if not required, some drivers seem to require we specify this. See #8254. - glPixelStorei(GL_PACK_ROW_LENGTH, pixelStride); - } - - glReadPixels(x, y, w, h, format, type, pixels); -#ifdef DEBUG_READ_PIXELS - LogReadPixelsError(glGetError()); -#endif - - if (!gl_extensions.IsGLES || gl_extensions.GLES3) { - glPixelStorei(GL_PACK_ROW_LENGTH, 0); - } - CHECK_GL_ERROR_IF_DEBUG(); - */ + GLuint aspect = 0; + if (channelBits & FB_COLOR_BIT) + aspect |= GL_COLOR_BUFFER_BIT; + if (channelBits & FB_DEPTH_BIT) + aspect |= GL_DEPTH_BUFFER_BIT; + if (channelBits & FB_STENCIL_BIT) + aspect |= GL_STENCIL_BUFFER_BIT; + renderManager_.CopyFramebufferToMemorySync(fb->framebuffer, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride); return true; } From 42f2312030ac58526f804892554203691dacb3fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 15 Dec 2017 12:40:38 +0100 Subject: [PATCH 028/291] Remove the old CPU threading remains, start redesigning interfaces. --- Common/GraphicsContext.h | 8 ++ Core/Core.h | 4 + Core/System.cpp | 172 +--------------------------- Core/System.h | 2 - Windows/EmuThread.cpp | 35 +++++- Windows/EmuThread.h | 2 +- Windows/GPU/WindowsGLContext.h | 2 +- Windows/MainWindow.cpp | 2 +- Windows/main.cpp | 4 +- ext/native/thin3d/GLQueueRunner.cpp | 4 +- 10 files changed, 56 insertions(+), 179 deletions(-) diff --git a/Common/GraphicsContext.h b/Common/GraphicsContext.h index c8495b04be..e32dd6c306 100644 --- a/Common/GraphicsContext.h +++ b/Common/GraphicsContext.h @@ -10,6 +10,11 @@ class GraphicsContext { public: virtual ~GraphicsContext() {} + // Threaded backends (that need to do init on the final render thread, like GL) + // call this from the render thread. Init() should block until InitFromThread is done. + // Other backends can ignore this. + virtual bool InitFromThread() { return true; } + virtual void Shutdown() = 0; virtual void SwapInterval(int interval) = 0; @@ -25,6 +30,9 @@ public: // Needs casting to the appropriate type, unfortunately. Should find a better solution.. virtual void *GetAPIContext() { return nullptr; } + // Called from the render thread from threaded backends. + virtual void ThreadFrame() {} + virtual Draw::DrawContext *GetDrawContext() = 0; }; diff --git a/Core/Core.h b/Core/Core.h index 98262f7beb..9adbd6356e 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -24,11 +24,15 @@ class GraphicsContext; // called from emu thread void UpdateRunLoop(); + void Core_Run(GraphicsContext *ctx); void Core_Stop(); void Core_ErrorPause(); // For platforms that don't call Core_Run void Core_SetGraphicsContext(GraphicsContext *ctx); + +void Core_RunRenderThreadFrame(); + // called from gui void Core_EnableStepping(bool step); void Core_DoSingleStep(); diff --git a/Core/System.cpp b/Core/System.cpp index cc41c39313..772f00e877 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -81,12 +81,7 @@ ParamSFOData g_paramSFO; static GlobalUIState globalUIState; static CoreParameter coreParameter; static FileLoader *loadedFile; -static std::thread *cpuThread = nullptr; -static std::thread::id cpuThreadID; -static std::mutex cpuThreadLock; -static std::condition_variable cpuThreadCond; -static std::condition_variable cpuThreadReplyCond; -static u64 cpuThreadUntil; + bool audioInitialized; bool coreCollectDebugStats = false; @@ -142,45 +137,6 @@ void Audio_Shutdown() { } } -bool IsOnSeparateCPUThread() { - if (cpuThread != nullptr) { - return cpuThreadID == std::this_thread::get_id(); - } else { - return false; - } -} - -void CPU_SetStateNoLock(CPUThreadState to) { - cpuThreadState = to; - cpuThreadCond.notify_one(); - cpuThreadReplyCond.notify_one(); -} - -void CPU_SetState(CPUThreadState to) { - std::lock_guard guard(cpuThreadLock); - CPU_SetStateNoLock(to); -} - -bool CPU_NextState(CPUThreadState from, CPUThreadState to) { - std::lock_guard guard(cpuThreadLock); - if (cpuThreadState == from) { - CPU_SetStateNoLock(to); - return true; - } else { - return false; - } -} - -bool CPU_NextStateNot(CPUThreadState from, CPUThreadState to) { - std::lock_guard guard(cpuThreadLock); - if (cpuThreadState != from) { - CPU_SetStateNoLock(to); - return true; - } else { - return false; - } -} - bool CPU_IsReady() { if (coreState == CORE_POWERUP) return false; @@ -195,13 +151,6 @@ bool CPU_HasPendingAction() { return cpuThreadState != CPU_THREAD_RUNNING; } -void CPU_WaitStatus(std::condition_variable &cond, bool (*pred)()) { - std::unique_lock guard(cpuThreadLock); - while (!pred()) { - cond.wait(guard); - } -} - void CPU_Shutdown(); void CPU_Init() { @@ -278,7 +227,6 @@ void CPU_Init() { if (!LoadFile(&loadedFile, &coreParameter.errorString)) { CPU_Shutdown(); coreParameter.fileToStart = ""; - CPU_SetState(CPU_THREAD_NOT_RUNNING); return; } @@ -321,52 +269,6 @@ void UpdateLoadedFile(FileLoader *fileLoader) { loadedFile = fileLoader; } -void CPU_RunLoop() { - setCurrentThreadName("CPU"); - - if (CPU_NextState(CPU_THREAD_PENDING, CPU_THREAD_STARTING)) { - CPU_Init(); - CPU_NextState(CPU_THREAD_STARTING, CPU_THREAD_RUNNING); - } else if (!CPU_NextState(CPU_THREAD_RESUME, CPU_THREAD_RUNNING)) { - ERROR_LOG(CPU, "CPU thread in unexpected state: %d", cpuThreadState); - return; - } - - while (cpuThreadState != CPU_THREAD_SHUTDOWN) - { - CPU_WaitStatus(cpuThreadCond, &CPU_HasPendingAction); - switch (cpuThreadState) { - case CPU_THREAD_EXECUTE: - mipsr4k.RunLoopUntil(cpuThreadUntil); - CPU_NextState(CPU_THREAD_EXECUTE, CPU_THREAD_RUNNING); - break; - - // These are fine, just keep looping. - case CPU_THREAD_RUNNING: - case CPU_THREAD_SHUTDOWN: - break; - - case CPU_THREAD_QUIT: - // Just leave the thread, CPU is switching off thread. - CPU_SetState(CPU_THREAD_NOT_RUNNING); - return; - - default: - ERROR_LOG(CPU, "CPU thread in unexpected state: %d", cpuThreadState); - // Begin shutdown, otherwise we'd just spin on this bad state. - CPU_SetState(CPU_THREAD_SHUTDOWN); - break; - } - } - - if (coreState != CORE_ERROR) { - coreState = CORE_POWERDOWN; - } - - CPU_Shutdown(); - CPU_SetState(CPU_THREAD_NOT_RUNNING); -} - void Core_UpdateState(CoreState newState) { if ((coreState == CORE_RUNNING || coreState == CORE_NEXTFRAME) && newState != CORE_RUNNING) coreStatePending = true; @@ -384,11 +286,6 @@ void Core_UpdateDebugStats(bool collectStats) { gpuStats.ResetFrame(); } -void System_Wake() { - // Ping the threads so they check coreState. - CPU_NextStateNot(CPU_THREAD_NOT_RUNNING, CPU_THREAD_SHUTDOWN); -} - // Ugly! static bool pspIsInited = false; static bool pspIsIniting = false; @@ -415,17 +312,7 @@ bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) { coreParameter.errorString = ""; pspIsIniting = true; - // Keeping this around because we might need it in the future. - const bool separateCPUThread = false; - if (separateCPUThread) { - Core_ListenShutdown(System_Wake); - CPU_SetState(CPU_THREAD_PENDING); - cpuThread = new std::thread(&CPU_RunLoop); - cpuThreadID = cpuThread->get_id(); - cpuThread->detach(); - } else { - CPU_Init(); - } + CPU_Init(); *error_string = coreParameter.errorString; bool success = coreParameter.fileToStart != ""; @@ -461,11 +348,6 @@ bool PSP_InitUpdate(std::string *error_string) { bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) { PSP_InitStart(coreParam, error_string); - // For a potential resurrection of separate CPU thread later. - if (false) { - CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady); - } - while (!PSP_InitUpdate(error_string)) sleep_ms(10); return pspIsInited; @@ -496,15 +378,7 @@ void PSP_Shutdown() { if (coreState == CORE_RUNNING) Core_UpdateState(CORE_ERROR); Core_NotifyShutdown(); - if (cpuThread != nullptr) { - CPU_NextStateNot(CPU_THREAD_NOT_RUNNING, CPU_THREAD_SHUTDOWN); - CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsShutdown); - delete cpuThread; - cpuThread = 0; - cpuThreadID = std::thread::id(); - } else { - CPU_Shutdown(); - } + CPU_Shutdown(); GPU_Shutdown(); g_paramSFO.Clear(); host->SetWindowTitle(0); @@ -534,45 +408,7 @@ void PSP_RunLoopUntil(u64 globalticks) { return; } - // We no longer allow a separate CPU thread but if we add a render queue - // to GL we're gonna need it. - bool useCPUThread = false; - if (useCPUThread && cpuThread == nullptr) { - // Need to start the cpu thread. - Core_ListenShutdown(System_Wake); - CPU_SetState(CPU_THREAD_RESUME); - cpuThread = new std::thread(&CPU_RunLoop); - cpuThreadID = cpuThread->get_id(); - cpuThread->detach(); - // Probably needs to tell the gpu that it will need to queue up its output - // on another thread. - CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady); - } else if (!useCPUThread && cpuThread != nullptr) { - CPU_SetState(CPU_THREAD_QUIT); - CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsShutdown); - delete cpuThread; - cpuThread = nullptr; - cpuThreadID = std::thread::id(); - } - - if (cpuThread != nullptr) { - cpuThreadUntil = globalticks; - if (CPU_NextState(CPU_THREAD_RUNNING, CPU_THREAD_EXECUTE)) { - // The CPU doesn't actually respect cpuThreadUntil well, especially when skipping frames. - // TODO: Something smarter? Or force CPU to bail periodically? - while (!CPU_IsReady()) { - // Have the GPU do stuff here. - if (coreState != CORE_RUNNING) { - CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady); - } - } - } else { - ERROR_LOG(CPU, "Unable to execute CPU run loop, unexpected state: %d", cpuThreadState); - } - } else { - mipsr4k.RunLoopUntil(globalticks); - } - + mipsr4k.RunLoopUntil(globalticks); gpu->CleanupBeforeUI(); } diff --git a/Core/System.h b/Core/System.h index 9cc4cfdc89..6017e88cc5 100644 --- a/Core/System.h +++ b/Core/System.h @@ -78,8 +78,6 @@ void Core_UpdateDebugStats(bool collectStats); void Audio_Init(); void Audio_Shutdown(); - -bool IsOnSeparateCPUThread(); bool IsAudioInitialised(); void UpdateLoadedFile(FileLoader *fileLoader); diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 87ae5f1d17..2617ed00c4 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -10,6 +10,7 @@ #include "Common/Log.h" #include "Common/StringUtils.h" +#include "Common/GraphicsContext.h" #include "Windows/EmuThread.h" #include "Windows/W32Util/Misc.h" #include "Windows/MainWindow.h" @@ -27,8 +28,18 @@ static std::mutex emuThreadLock; static std::thread emuThread; static std::atomic emuThreadState; +static std::mutex renderThreadLock; +static std::thread renderThread; +static std::atomic renderThreadReady; + +static bool useRenderThread; + extern std::vector GetWideCmdLine(); +class GraphicsContext; + +static GraphicsContext *g_graphicsContext; + enum EmuThreadStatus : int { THREAD_NONE = 0, THREAD_INIT, @@ -38,10 +49,15 @@ enum EmuThreadStatus : int { }; void EmuThreadFunc(); +void RenderThreadFunc(); -void EmuThread_Start() { +void EmuThread_Start(bool separateRenderThread) { std::lock_guard guard(emuThreadLock); emuThread = std::thread(&EmuThreadFunc); + useRenderThread = separateRenderThread; + if (useRenderThread) { + renderThread = std::thread(&RenderThreadFunc); + } } void EmuThread_Stop() { @@ -56,6 +72,9 @@ void EmuThread_Stop() { Core_Stop(); Core_WaitInactive(800); emuThread.join(); + if (useRenderThread) { + renderThread.join(); + } PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_UPDATE_UI, 0, 0); } @@ -64,6 +83,19 @@ bool EmuThread_Ready() { return emuThreadState == THREAD_CORE_LOOP; } +void RenderThreadFunc() { + setCurrentThreadName("Render"); + while (!g_graphicsContext) { + sleep_ms(50); + continue; + } + g_graphicsContext->InitFromThread(); + while (true) { + g_graphicsContext->ThreadFrame(); + break; + } +} + void EmuThreadFunc() { emuThreadState = THREAD_INIT; @@ -175,4 +207,3 @@ shutdown: emuThreadState = THREAD_END; } - diff --git a/Windows/EmuThread.h b/Windows/EmuThread.h index ed1a9df08d..d232fefb14 100644 --- a/Windows/EmuThread.h +++ b/Windows/EmuThread.h @@ -17,6 +17,6 @@ #pragma once -void EmuThread_Start(); +void EmuThread_Start(bool separateRenderThread); void EmuThread_Stop(); bool EmuThread_Ready(); diff --git a/Windows/GPU/WindowsGLContext.h b/Windows/GPU/WindowsGLContext.h index 3fe2f9f4a8..4ddd28ba61 100644 --- a/Windows/GPU/WindowsGLContext.h +++ b/Windows/GPU/WindowsGLContext.h @@ -10,6 +10,7 @@ namespace Draw { class WindowsGLContext : public WindowsGraphicsContext { public: bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override; + void Shutdown() override; void SwapInterval(int interval) override; void SwapBuffers() override; @@ -18,7 +19,6 @@ public: // not the rendering thread or CPU thread. void Pause() override; void Resume() override; - void Resize() override; Draw::DrawContext *GetDrawContext() override { return draw_; } diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index f56ade7bce..a3c45e3567 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -917,7 +917,7 @@ namespace MainWindow EmuThread_Stop(); coreState = CORE_POWERUP; ResetUIState(); - EmuThread_Start(); + EmuThread_Start(false); InputDevice::BeginPolling(); break; diff --git a/Windows/main.cpp b/Windows/main.cpp index 4d6a28c849..5bbe6ec01a 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -529,8 +529,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin MainWindow::Minimize(); } - // Emu thread is always running! - EmuThread_Start(); + // Emu thread (and render thread, if any) is always running! + EmuThread_Start(false); // g_Config.iGPUBackend == GPU_BACKEND_VULKAN); InputDevice::BeginPolling(); HACCEL hAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_ACCELS); diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 21d78f757d..1e3597fdb5 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -889,8 +889,8 @@ void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) { void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { // TODO: Maybe move data format conversion here, and always read back 8888. Drivers - // don't usually provide very optimized implementations. - int bpp = Draw::DataFormatSizeInBytes(destFormat); + // don't usually provide very optimized conversion implementations, though some do. + int bpp = (int)Draw::DataFormatSizeInBytes(destFormat); for (int y = 0; y < height; y++) { memcpy(pixels + y * pixelStride * bpp, readbackBuffer_ + y * width * bpp, pixelStride * bpp); } From 63b9140ebfe85de5bbfa9ff4acbfde8c483ea568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 21 Dec 2017 15:38:55 +0100 Subject: [PATCH 029/291] Rip out async readbacks from FramebufferManagerGLES. They should be implemented in GLQueueRunner, differently. --- GPU/Common/FramebufferCommon.h | 2 +- GPU/GLES/FramebufferManagerGLES.cpp | 161 +--------------------------- GPU/GLES/FramebufferManagerGLES.h | 41 ++----- 3 files changed, 13 insertions(+), 191 deletions(-) diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 8545115e86..9cf359bfa9 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -224,7 +224,7 @@ public: virtual void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h); - virtual void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes); + void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes); void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader); void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index dbfa48c1ad..9902871089 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -238,18 +238,7 @@ void FramebufferManagerGLES::BindPostShader(const PostShaderUniforms &uniforms) FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render) : FramebufferManagerCommon(draw), - render_(render), - drawPixelsTex_(0), - drawPixelsTexFormat_(GE_FORMAT_INVALID), - convBuf_(nullptr), - videoLoc_(-1), - timeLoc_(-1), - pixelDeltaLoc_(-1), - deltaLoc_(-1), - textureCacheGL_(nullptr), - shaderManagerGL_(nullptr), - pixelBufObj_(nullptr), - currentPBO_(0) + render_(render) { needBackBufferYSwap_ = true; needGLESRebinds_ = true; @@ -315,14 +304,6 @@ void FramebufferManagerGLES::DestroyDeviceObjects() { FramebufferManagerGLES::~FramebufferManagerGLES() { DestroyDeviceObjects(); - if (pixelBufObj_) { - for (int i = 0; i < MAX_PBO; i++) { - if (pixelBufObj_[i].buffer) { - render_->DeleteBuffer(pixelBufObj_[i].buffer); - } - } - delete[] pixelBufObj_; - } delete [] convBuf_; } @@ -540,46 +521,19 @@ void FramebufferManagerGLES::BindFramebufferAsColorTexture(int stage, VirtualFra void FramebufferManagerGLES::ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) { PROFILE_THIS_SCOPE("gpu-readback"); - if (sync) { - // flush async just in case when we go for synchronous update - // Doesn't actually pack when sent a null argument. - PackFramebufferAsync_(nullptr); - } - if (vfb) { // We'll pseudo-blit framebuffers here to get a resized version of vfb. VirtualFramebuffer *nvfb = FindDownloadTempBuffer(vfb); OptimizeDownloadRange(vfb, x, y, w, h); BlitFramebuffer(nvfb, x, y, vfb, x, y, w, h, 0); - // PackFramebufferSync_() - Synchronous pixel data transfer using glReadPixels - // PackFramebufferAsync_() - Asynchronous pixel data transfer using glReadPixels with PBOs - - if (gl_extensions.IsGLES) { - PackFramebufferSync_(nvfb, x, y, w, h); - } else { - // TODO: Can we fall back to sync without these? - if (gl_extensions.ARB_pixel_buffer_object && gstate_c.Supports(GPU_SUPPORTS_OES_TEXTURE_NPOT)) { - if (!sync) { - PackFramebufferAsync_(nvfb); - } else { - PackFramebufferSync_(nvfb, x, y, w, h); - } - } - } + PackFramebufferSync_(nvfb, x, y, w, h); textureCacheGL_->ForgetLastTexture(); RebindFramebuffer(); } } -void FramebufferManagerGLES::DownloadFramebufferForClut(u32 fb_address, u32 loadBytes) { - PROFILE_THIS_SCOPE("gpu-readback"); - // Flush async just in case. - PackFramebufferAsync_(nullptr); - FramebufferManagerCommon::DownloadFramebufferForClut(fb_address, loadBytes); -} - bool FramebufferManagerGLES::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) { // When updating VRAM, it need to be exact format. if (!gstate_c.Supports(GPU_PREFER_CPU_DOWNLOAD)) { @@ -758,117 +712,6 @@ void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u } } -void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) { - GLubyte *packed = 0; - bool unbind = false; - const u8 nextPBO = (currentPBO_ + 1) % MAX_PBO; - const bool useCPU = gstate_c.Supports(GPU_PREFER_CPU_DOWNLOAD); - - // We'll prepare two PBOs to switch between readying and reading - if (!pixelBufObj_) { - if (!vfb) { - // This call is just to flush the buffers. We don't have any yet, - // so there's nothing to do. - return; - } - - pixelBufObj_ = new AsyncPBO[MAX_PBO]{}; - } - - // Receive previously requested data from a PBO - AsyncPBO &pbo = pixelBufObj_[nextPBO]; - if (pbo.reading) { - render_->BindPixelPackBuffer(pbo.buffer); -#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 - - if (packed) { - DEBUG_LOG(FRAMEBUF, "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) { - 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); - } - - pbo.reading = false; - } - - glUnmapBuffer(GL_PIXEL_PACK_BUFFER); - unbind = true; - } - - // Order packing/readback of the framebuffer - if (vfb) { - bool reverseOrder = gstate_c.Supports(GPU_PREFER_REVERSE_COLOR_ORDER); - Draw::DataFormat dataFmt = Draw::DataFormat::UNDEFINED; - switch (vfb->format) { - case GE_FORMAT_4444: - dataFmt = (reverseOrder ? Draw::DataFormat::A4R4G4B4_UNORM_PACK16 : Draw::DataFormat::B4G4R4A4_UNORM_PACK16); - break; - case GE_FORMAT_5551: - dataFmt = (reverseOrder ? Draw::DataFormat::A1R5G5B5_UNORM_PACK16 : Draw::DataFormat::B5G5R5A1_UNORM_PACK16); - break; - case GE_FORMAT_565: - dataFmt = (reverseOrder ? Draw::DataFormat::R5G6B5_UNORM_PACK16 : Draw::DataFormat::B5G6R5_UNORM_PACK16); - break; - case GE_FORMAT_8888: - dataFmt = Draw::DataFormat::R8G8B8A8_UNORM; - break; - }; - - if (useCPU) { - dataFmt = Draw::DataFormat::R8G8B8A8_UNORM; - } - - int pixelSize = (int)DataFormatSizeInBytes(dataFmt); - int align = pixelSize; - - // If using the CPU, we need 4 bytes per pixel always. - u32 bufSize = vfb->fb_stride * vfb->height * pixelSize; - u32 fb_address = (0x04000000) | vfb->fb_address; - - if (!vfb->fbo) { - ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferAsync_: vfb->fbo == 0"); - return; - } - - if (pixelBufObj_[currentPBO_].maxSize < bufSize) { - if (pixelBufObj_[currentPBO_].buffer) { - render_->DeleteBuffer(pixelBufObj_[currentPBO_].buffer); - } - pixelBufObj_[currentPBO_].buffer = render_->CreateBuffer(GL_PIXEL_PACK_BUFFER, bufSize, GL_DYNAMIC_READ); - pixelBufObj_[currentPBO_].maxSize = bufSize; - } - - render_->BindPixelPackBuffer(pixelBufObj_[currentPBO_].buffer); - // TODO: This is a hack since PBOs have not been implemented in Thin3D yet (and maybe shouldn't? maybe should do this internally?) - draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, 0, 0, vfb->fb_stride, vfb->height, dataFmt, nullptr, vfb->fb_stride); - - unbind = true; - - pixelBufObj_[currentPBO_].fb_address = fb_address; - pixelBufObj_[currentPBO_].size = bufSize; - pixelBufObj_[currentPBO_].stride = vfb->fb_stride; - pixelBufObj_[currentPBO_].height = vfb->height; - pixelBufObj_[currentPBO_].format = vfb->format; - pixelBufObj_[currentPBO_].reading = true; - } - - currentPBO_ = nextPBO; - - if (unbind) { - render_->BindPixelPackBuffer(0); - } -} - void FramebufferManagerGLES::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h) { if (!vfb->fbo) { ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferSync_: vfb->fbo == 0"); diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 60c5c841ad..969194babb 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -36,19 +36,6 @@ class TextureCacheGLES; class DrawEngineGLES; class ShaderManagerGLES; -// Simple struct for asynchronous PBO readbacks -struct AsyncPBO { - GLRBuffer *buffer; - u32 maxSize; - - u32 fb_address; - u32 stride; - u32 height; - u32 size; - GEBufferFormat format; - bool reading; -}; - class FramebufferManagerGLES : public FramebufferManagerCommon { public: FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render); @@ -67,7 +54,6 @@ public: void EndFrame(); void Resized() override; void DeviceLost(); - void SetLineWidth(); void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override; void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) override; @@ -77,7 +63,6 @@ public: // Reads a rectangular subregion of a framebuffer to the right position in its backing memory. void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) override; - void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes) override; bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; @@ -105,24 +90,22 @@ private: void CompileDraw2DProgram(); void CompilePostShader(); - void PackFramebufferAsync_(VirtualFramebuffer *vfb); // Not used under ES currently void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h) override; void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); GLRenderManager *render_; // Used by DrawPixels - GLRTexture *drawPixelsTex_; - GEBufferFormat drawPixelsTexFormat_; - int drawPixelsTexW_; - int drawPixelsTexH_; + GLRTexture *drawPixelsTex_ = nullptr; + GEBufferFormat drawPixelsTexFormat_ = GE_FORMAT_INVALID; + int drawPixelsTexW_ = 0; + int drawPixelsTexH_ = 0; - u8 *convBuf_; - u32 convBufSize_; + u8 *convBuf_ = nullptr; + u32 convBufSize_ = 0; GLRProgram *draw2dprogram_ = nullptr; GLRProgram *postShaderProgram_ = nullptr; - GLRProgram *stencilUploadProgram_ = nullptr; int u_stencilUploadTex = -1; int u_stencilValue = -1; @@ -137,17 +120,13 @@ private: int pixelDeltaLoc_ = -1; int deltaLoc_ = -1; - TextureCacheGLES *textureCacheGL_; - ShaderManagerGLES *shaderManagerGL_; - DrawEngineGLES *drawEngineGL_; + TextureCacheGLES *textureCacheGL_ = nullptr; + ShaderManagerGLES *shaderManagerGL_ = nullptr; + DrawEngineGLES *drawEngineGL_ = nullptr; struct Simple2DVertex { float pos[3]; float uv[2]; }; - GLRInputLayout *simple2DInputLayout_; - - // Not used under ES currently. - AsyncPBO *pixelBufObj_; //this isn't that large - u8 currentPBO_; + GLRInputLayout *simple2DInputLayout_ = nullptr; }; From 542f9f9ef1f095d9d2b498b49b90d74539817071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 21 Dec 2017 19:05:33 +0100 Subject: [PATCH 030/291] Assorted cleanup --- GPU/Common/FramebufferCommon.h | 2 +- GPU/GLES/DrawEngineGLES.cpp | 2 +- GPU/GLES/FramebufferManagerGLES.cpp | 68 --------------------------- GPU/GLES/FramebufferManagerGLES.h | 4 -- Windows/GPU/WindowsGLContext.cpp | 35 ++++++-------- ext/native/thin3d/GLQueueRunner.cpp | 5 -- ext/native/thin3d/GLRenderManager.cpp | 7 +++ 7 files changed, 23 insertions(+), 100 deletions(-) diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 9cf359bfa9..9ab59a4b0b 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -222,7 +222,7 @@ public: bool NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp, u32 skipDrawReason); void NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp, u32 skipDrawReason); - virtual void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h); + void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h); void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes); void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader); diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 1cf8e67af5..225ad05ce7 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -156,7 +156,7 @@ void DrawEngineGLES::DeviceRestore() { void DrawEngineGLES::InitDeviceObjects() { for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { frameData_[i].pushVertex = new GLPushBuffer(render_, GL_ARRAY_BUFFER, 1024 * 1024); - frameData_[i].pushIndex = new GLPushBuffer(render_, GL_ELEMENT_ARRAY_BUFFER, 512 * 1024); + frameData_[i].pushIndex = new GLPushBuffer(render_, GL_ELEMENT_ARRAY_BUFFER, 256 * 1024); } int vertexSize = sizeof(TransformedVertex); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 9902871089..7e117d3dda 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -519,21 +519,6 @@ void FramebufferManagerGLES::BindFramebufferAsColorTexture(int stage, VirtualFra } } -void FramebufferManagerGLES::ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) { - PROFILE_THIS_SCOPE("gpu-readback"); - if (vfb) { - // We'll pseudo-blit framebuffers here to get a resized version of vfb. - VirtualFramebuffer *nvfb = FindDownloadTempBuffer(vfb); - OptimizeDownloadRange(vfb, x, y, w, h); - BlitFramebuffer(nvfb, x, y, vfb, x, y, w, h, 0); - - PackFramebufferSync_(nvfb, x, y, w, h); - - textureCacheGL_->ForgetLastTexture(); - RebindFramebuffer(); - } -} - bool FramebufferManagerGLES::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) { // When updating VRAM, it need to be exact format. if (!gstate_c.Supports(GPU_PREFER_CPU_DOWNLOAD)) { @@ -568,8 +553,6 @@ void FramebufferManagerGLES::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) // Discard the previous contents of this buffer where possible. if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) { draw_->BindFramebufferAsRenderTarget(nvfb->fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); - GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT }; - glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments); } else if (gl_extensions.IsGLES) { draw_->BindFramebufferAsRenderTarget(nvfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); } @@ -712,57 +695,6 @@ void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u } } -void FramebufferManagerGLES::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h) { - if (!vfb->fbo) { - ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferSync_: vfb->fbo == 0"); - return; - } - - int possibleH = std::max(vfb->height - y, 0); - if (h > possibleH) { - h = possibleH; - } - - bool convert = vfb->format != GE_FORMAT_8888; - const int dstBpp = vfb->format == GE_FORMAT_8888 ? 4 : 2; - const int packWidth = std::min(vfb->fb_stride, std::min(x + w, (int)vfb->width)); - - // Pixel size always 4 here because we always request RGBA8888 - u32 bufSize = packWidth * h * 4; - u32 fb_address = 0x04000000 | vfb->fb_address; - - if (gl_extensions.IsGLES && !gl_extensions.GLES3 && packWidth != vfb->fb_stride && h != 1) { - // Need to use a temp buffer, since GLES2 doesn't support GL_PACK_ROW_LENGTH. - convert = true; - } - - int dstByteOffset = y * vfb->fb_stride * dstBpp; - u8 *dst = Memory::GetPointer(fb_address + dstByteOffset); - - u8 *packed = nullptr; - if (!convert) { - packed = (u8 *)dst; - } else { - // End result may be 16-bit but we are reading 32-bit, so there may not be enough space at fb_address - if (!convBuf_ || convBufSize_ < bufSize) { - delete [] convBuf_; - convBuf_ = new u8[bufSize]; - convBufSize_ = bufSize; - } - packed = convBuf_; - } - - if (packed) { - DEBUG_LOG(FRAMEBUF, "Reading framebuffer to mem, bufSize = %u, fb_address = %08x", bufSize, fb_address); - // Avoid reading the part between width and stride, if possible. - int packStride = convert || h == 1 ? packWidth : vfb->fb_stride; - draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, 0, y, packWidth, h, Draw::DataFormat::R8G8B8A8_UNORM, packed, packStride); - if (convert) { - ConvertFromRGBA8888(dst, packed, vfb->fb_stride, packStride, packWidth, h, vfb->format); - } - } -} - void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) { if (!vfb->fbo) { ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackDepthbuffer: vfb->fbo == 0"); diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 969194babb..c3f0594637 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -61,9 +61,6 @@ public: // For use when texturing from a framebuffer. May create a duplicate if target. void BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags); - // Reads a rectangular subregion of a framebuffer to the right position in its backing memory. - void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) override; - bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; @@ -90,7 +87,6 @@ private: void CompileDraw2DProgram(); void CompilePostShader(); - void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h) override; void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); GLRenderManager *render_; diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 283797b064..100814f5b0 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -35,7 +35,6 @@ void WindowsGLContext::SwapBuffers() { ::SwapBuffers(hDC); - // Used during fullscreen switching to prevent rendering. if (pauseRequested) { SetEvent(pauseEvent); @@ -46,10 +45,6 @@ void WindowsGLContext::SwapBuffers() { } pauseRequested = false; } - - // According to some sources, doing this *after* swapbuffers can reduce frame latency - // at a large performance cost. So let's not. - // glFinish(); } void WindowsGLContext::Pause() { @@ -96,7 +91,7 @@ void FormatDebugOutputARB(char outStr[], size_t outStrSize, GLenum source, GLenu case GL_DEBUG_SOURCE_APPLICATION_ARB: sourceFmt = "APPLICATION"; break; case GL_DEBUG_SOURCE_OTHER_ARB: sourceFmt = "OTHER"; break; } - _snprintf(sourceStr, 32, sourceFmt, source); + snprintf(sourceStr, sizeof(sourceStr), sourceFmt, source); char typeStr[32]; const char *typeFmt = "UNDEFINED(0x%04X)"; @@ -108,30 +103,27 @@ void FormatDebugOutputARB(char outStr[], size_t outStrSize, GLenum source, GLenu case GL_DEBUG_TYPE_PERFORMANCE_ARB: typeFmt = "PERFORMANCE"; break; case GL_DEBUG_TYPE_OTHER_ARB: typeFmt = "OTHER"; break; } - _snprintf(typeStr, 32, typeFmt, type); + snprintf(typeStr, sizeof(typeStr), typeFmt, type); char severityStr[32]; const char *severityFmt = "UNDEFINED"; - switch(severity) - { - case GL_DEBUG_SEVERITY_HIGH_ARB: severityFmt = "HIGH"; break; + switch (severity) { + case GL_DEBUG_SEVERITY_HIGH_ARB: severityFmt = "HIGH"; break; case GL_DEBUG_SEVERITY_MEDIUM_ARB: severityFmt = "MEDIUM"; break; case GL_DEBUG_SEVERITY_LOW_ARB: severityFmt = "LOW"; break; } - _snprintf(severityStr, 32, severityFmt, severity); - - _snprintf(outStr, outStrSize, "OpenGL: %s [source=%s type=%s severity=%s id=%d]\n", msg, sourceStr, typeStr, severityStr, id); + snprintf(severityStr, sizeof(severityStr), severityFmt, severity); + snprintf(outStr, sizeof(outStr), "OpenGL: %s [source=%s type=%s severity=%s id=%d]\n", msg, sourceStr, typeStr, severityStr, id); } void DebugCallbackARB(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam) { (void)length; - FILE *outFile = (FILE*)userParam; + FILE *outFile = (FILE *)userParam; char finalMessage[256]; FormatDebugOutputARB(finalMessage, 256, source, type, id, severity, message); OutputDebugStringA(finalMessage); - switch (type) { case GL_DEBUG_TYPE_ERROR_ARB: case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: @@ -153,6 +145,7 @@ void DebugCallbackARB(GLenum source, GLenum type, GLuint id, GLenum severity, bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_message) { glslang::InitializeProcess(); + *error_message = "ok"; hWnd = window; GLuint PixelFormat; @@ -186,7 +179,7 @@ bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_mes return false; // Return FALSE } - if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) { + if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) { *error_message = "Can't find a suitable PixelFormat."; return false; } @@ -196,7 +189,7 @@ bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_mes return false; } - if (!(hRC = wglCreateContext(hDC))) { + if (!(hRC = wglCreateContext(hDC))) { *error_message = "Can't create a GL rendering context."; return false; } @@ -225,7 +218,7 @@ bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_mes HDC dc = GetDC(NULL); u32 colour_depth = GetDeviceCaps(dc, BITSPIXEL); ReleaseDC(NULL, dc); - if (colour_depth != 32){ + if (colour_depth != 32) { MessageBox(0, L"Please switch your display to 32-bit colour mode", L"OpenGL Error", MB_OK); ExitProcess(1); } @@ -383,12 +376,12 @@ void WindowsGLContext::Shutdown() { if (hRC) { // Are we able to release the DC and RC contexts? if (!wglMakeCurrent(NULL,NULL)) { - MessageBox(NULL,L"Release of DC and RC failed.", L"SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); + MessageBox(NULL, L"Release of DC and RC failed.", L"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); } // Are we able to delete the RC? if (!wglDeleteContext(hRC)) { - MessageBox(NULL,L"Release rendering context failed.", L"SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); + MessageBox(NULL, L"Release rendering context failed.", L"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); } hRC = NULL; } @@ -396,7 +389,7 @@ void WindowsGLContext::Shutdown() { if (hDC && !ReleaseDC(hWnd,hDC)) { DWORD err = GetLastError(); if (err != ERROR_DC_NOT_FOUND) { - MessageBox(NULL,L"Release device context failed.", L"SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); + MessageBox(NULL, L"Release device context failed.", L"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); } hDC = NULL; } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 1e3597fdb5..8e02ffe1bd 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -919,11 +919,6 @@ void GLQueueRunner::fbo_ext_create(const GLRInitStep &step) { // Create the surfaces. glBindTexture(GL_TEXTURE_2D, fbo->color_texture); - 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_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 27b9fe6ad3..c78dc26a66 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -15,21 +15,27 @@ void GLDeleter::Perform() { for (auto shader : shaders) { delete shader; } + shaders.clear(); for (auto program : programs) { delete program; } + programs.clear(); for (auto buffer : buffers) { delete buffer; } + buffers.clear(); for (auto texture : textures) { delete texture; } + textures.clear(); for (auto inputLayout : inputLayouts) { delete inputLayout; } + inputLayouts.clear(); for (auto framebuffer : framebuffers) { delete framebuffer; } + framebuffers.clear(); } GLRenderManager::GLRenderManager() { @@ -46,6 +52,7 @@ GLRenderManager::~GLRenderManager() { for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { } + if (!useThread_) { queueRunner_.DestroyDeviceObjects(); } From af8e825578ea1b958c296bebb8f6c1220586482d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 27 Dec 2017 12:44:46 +0100 Subject: [PATCH 031/291] Fix terrible drawing glitches when we do sync readbacks. --- GPU/GLES/DrawEngineGLES.cpp | 5 +++++ ext/native/thin3d/GLRenderManager.cpp | 15 ++++++++++++++- ext/native/thin3d/GLRenderManager.h | 16 ++++++++++++++++ ext/native/thin3d/thin3d_gl.cpp | 2 ++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 225ad05ce7..d6d803ed12 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -157,6 +157,9 @@ void DrawEngineGLES::InitDeviceObjects() { for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { frameData_[i].pushVertex = new GLPushBuffer(render_, GL_ARRAY_BUFFER, 1024 * 1024); frameData_[i].pushIndex = new GLPushBuffer(render_, GL_ELEMENT_ARRAY_BUFFER, 256 * 1024); + + render_->RegisterPushBuffer(i, frameData_[i].pushVertex); + render_->RegisterPushBuffer(i, frameData_[i].pushIndex); } int vertexSize = sizeof(TransformedVertex); @@ -170,6 +173,8 @@ void DrawEngineGLES::InitDeviceObjects() { void DrawEngineGLES::DestroyDeviceObjects() { for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { + render_->UnregisterPushBuffer(i, frameData_[i].pushVertex); + render_->UnregisterPushBuffer(i, frameData_[i].pushIndex); frameData_[i].pushVertex->Destroy(); frameData_[i].pushIndex->Destroy(); delete frameData_[i].pushVertex; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index c78dc26a66..452497d3e2 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -379,6 +379,11 @@ void GLRenderManager::Run(int frame) { } void GLRenderManager::FlushSync() { + // Need to flush any pushbuffers to VRAM before submitting draw calls. + for (auto iter : frameData_[curFrame_].activePushBuffers) { + iter->Flush(); + } + // TODO: Reset curRenderStep_? int curFrame = curFrame_; FrameData &frameData = frameData_[curFrame]; @@ -465,6 +470,14 @@ void GLPushBuffer::Unmap() { writePtr_ = nullptr; } +void GLPushBuffer::Flush() { + render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].deviceMemory, false); + // Here we will submit all the draw calls, with the already known buffer and offsets. + // Might as well reset the write pointer here and start over the current buffer. + writePtr_ = buffers_[buf_].deviceMemory; + offset_ = 0; +} + bool GLPushBuffer::AddBuffer() { BufInfo info; info.deviceMemory = new uint8_t[size_]; @@ -527,4 +540,4 @@ size_t GLPushBuffer::GetTotalSize() const { sum += size_ * (buffers_.size() - 1); sum += offset_; return sum; -} +} \ No newline at end of file diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index de559fcc31..59d753537e 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include "GLQueueRunner.h" class GLRInputLayout; +class GLPushBuffer; class GLRFramebuffer { public: @@ -596,6 +598,17 @@ public: queueRunner_.Resize(width, height); } + // When using legacy functionality for push buffers (glBufferData), we need to flush them + // before actually making the glDraw* calls. It's best if the render manager handles that. + void RegisterPushBuffer(int frame, GLPushBuffer *buffer) { + frameData_[frame].activePushBuffers.insert(buffer); + } + void UnregisterPushBuffer(int frame, GLPushBuffer *buffer) { + auto iter = frameData_[frame].activePushBuffers.find(buffer); + _assert_(iter != frameData_[frame].activePushBuffers.end()); + frameData_[frame].activePushBuffers.erase(iter); + } + private: void BeginSubmitFrame(int frame); void EndSubmitFrame(int frame); @@ -629,6 +642,7 @@ private: uint32_t curSwapchainImage = -1; GLDeleter deleter; + std::set activePushBuffers; }; FrameData frameData_[MAX_INFLIGHT_FRAMES]; @@ -749,6 +763,8 @@ public: size_t GetTotalSize() const; + void Flush(); + private: bool AddBuffer(); void NextBuffer(size_t minSize); diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 194d065ec0..cf05ae4b75 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -526,11 +526,13 @@ OpenGLContext::OpenGLContext() { } for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { frameData_[i].push = new GLPushBuffer(&renderManager_, GL_ARRAY_BUFFER, 64 * 1024); + renderManager_.RegisterPushBuffer(i, frameData_[i].push); } } OpenGLContext::~OpenGLContext() { for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { + renderManager_.UnregisterPushBuffer(i, frameData_[i].push); frameData_[i].push->Destroy(); delete frameData_[i].push; } From 43ebbbcdb6c210e699eb4f51ed759e2eece2a629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 27 Dec 2017 13:03:04 +0100 Subject: [PATCH 032/291] More state dirtying, a comment --- GPU/Common/FramebufferCommon.cpp | 5 ++--- ext/native/thin3d/GLRenderManager.h | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 7425c88761..bb161849b3 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -1930,9 +1930,8 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB buffer.Allocate(w, h, GE_FORMAT_8888, flipY, true); bool retval = draw_->CopyFramebufferToMemorySync(bound, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w); gpuStats.numReadbacks++; - // Vulkan requires us to re-apply all dynamic state for each command buffer, and the above will cause us to start a new cmdbuf. - // So let's dirty the things that are involved in Vulkan dynamic state. Readbacks are not frequent so this won't hurt other backends. - gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE); + // After a readback we'll have flushed and started over, need to dirty a bunch of things to be safe. + gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); // We may have blitted to a temp FBO. RebindFramebuffer(); return retval; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 59d753537e..e712482ddf 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -113,6 +113,7 @@ public: } GLuint texture; GLenum target; + // TODO: Move sampler params here so we can move the dirty-tracking from TextureCacheGLES to here. }; class GLRBuffer { From 5c7c7ce1926547ab96f2c6afb60561968f834582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 27 Dec 2017 14:33:18 +0100 Subject: [PATCH 033/291] Move GL sampler state tracking into GLRenderManager/QueueRunner. --- GPU/Common/FramebufferCommon.cpp | 2 + GPU/Common/TextureCacheCommon.h | 8 ---- GPU/Directx9/TextureCacheDX9.cpp | 1 - GPU/GLES/TextureCacheGLES.cpp | 13 ++---- ext/native/thin3d/GLQueueRunner.cpp | 72 ++++++++++++++++++++++------- ext/native/thin3d/GLRenderManager.h | 14 ++++-- 6 files changed, 72 insertions(+), 38 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index bb161849b3..c0d747802f 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -1965,6 +1965,8 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 } // No need to free on failure, that's the caller's job (it likely will reuse a buffer.) bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w); + // After a readback we'll have flushed and started over, need to dirty a bunch of things to be safe. + gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); // That may have unbound the framebuffer, rebind to avoid crashes when debugging. RebindFramebuffer(); return retval; diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index aa69f123a5..1bc16a2541 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -148,16 +148,8 @@ struct TexCacheEntry { u32 framesUntilNextFullHash; u32 fullhash; u32 cluthash; - float lodBias; u16 maxSeenV; - // Cache the current filter settings so we can avoid setting it again. - // (OpenGL ES 2.0 madness where filter settings are attached to each texture. Unused in other backends). - u8 magFilt; - u8 minFilt; - bool sClamp; - bool tClamp; - TexStatus GetHashStatus() { return TexStatus(status & STATUS_MASK); } diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 123eebd0ff..53e69baa56 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -171,7 +171,6 @@ void TextureCacheDX9::UpdateSamplingParams(TexCacheEntry &entry, bool force) { dxstate.texMaxMipLevel.set(0); dxstate.texMipLodBias.set(0.0f); } - entry.lodBias = lodBias; } else { dxstate.texMaxMipLevel.set(0); dxstate.texMipLodBias.set(0.0f); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 3ff8704bca..8560438e04 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -130,7 +130,7 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { float maxLod = 0.0f; if (maxLevel != 0) { // TODO: What about a swap of autoMip mode? - if (force || entry.lodBias != lodBias) { + if (true) { if (mode == GE_TEXLEVEL_MODE_AUTO) { minLod = 0.0f; maxLod = (float)maxLevel; @@ -147,7 +147,6 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { minLod = 0.0f; maxLod = (float)maxLevel; } - entry.lodBias = lodBias; } } else { minLod = 0.0f; @@ -156,14 +155,8 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { render_->SetTextureLod(minLod, maxLod, lodBias); } - if (force || entry.minFilt != minFilt || entry.magFilt != magFilt || entry.sClamp != sClamp || entry.tClamp != tClamp) { - float aniso = 0.0f; - render_->SetTextureSampler(sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); - entry.minFilt = minFilt; - entry.magFilt = magFilt; - entry.sClamp = sClamp; - entry.tClamp = tClamp; - } + float aniso = 0.0f; + render_->SetTextureSampler(sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); CHECK_GL_ERROR_IF_DEBUG(); } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 8e02ffe1bd..872d7b03dd 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -409,8 +409,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { GLRFramebuffer *fb = step.render.framebuffer; GLRProgram *curProgram = nullptr; - int activeTexture = 0; - glActiveTexture(GL_TEXTURE0 + activeTexture); + int activeSlot = 0; + glActiveTexture(GL_TEXTURE0 + activeSlot); // State filtering tracking. int attrMask = 0; @@ -426,6 +426,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { GLuint blendEqColor = (GLuint)-1; GLuint blendEqAlpha = (GLuint)-1; + GLRTexture *curTex[8]{}; + auto &commands = step.commands; for (const auto &c : commands) { switch (c.cmd) { @@ -604,23 +606,27 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { case GLRRenderCommand::BINDTEXTURE: { GLint slot = c.texture.slot; - if (slot != activeTexture) { + if (slot != activeSlot) { glActiveTexture(GL_TEXTURE0 + slot); - activeTexture = slot; + activeSlot = slot; } if (c.texture.texture) { - glBindTexture(c.texture.texture->target, c.texture.texture->texture); + if (curTex[slot] != c.texture.texture) { + glBindTexture(c.texture.texture->target, c.texture.texture->texture); + curTex[slot] = c.texture.texture; + } } else { glBindTexture(GL_TEXTURE_2D, 0); // Which target? Well we only use this one anyway... + curTex[slot] = nullptr; } break; } case GLRRenderCommand::BIND_FB_TEXTURE: { GLint slot = c.bind_fb_texture.slot; - if (slot != activeTexture) { + if (slot != activeSlot) { glActiveTexture(GL_TEXTURE0 + slot); - activeTexture = slot; + activeSlot = slot; } if (c.bind_fb_texture.aspect == GL_COLOR_BUFFER_BIT) { glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->color_texture); @@ -695,21 +701,55 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } break; case GLRRenderCommand::TEXTURESAMPLER: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter); - if (c.textureSampler.anisotropy != 0.0f) { + { + GLRTexture *tex = curTex[activeSlot]; + if (!tex) { + break; + } + if (tex->wrapS != c.textureSampler.wrapS) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS); + tex->wrapS = c.textureSampler.wrapS; + } + if (tex->wrapT != c.textureSampler.wrapT) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT); + tex->wrapT = c.textureSampler.wrapT; + } + if (tex->magFilter != c.textureSampler.magFilter) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter); + tex->magFilter = c.textureSampler.magFilter; + } + if (tex->minFilter != c.textureSampler.minFilter) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter); + tex->minFilter = c.textureSampler.minFilter; + } + if (tex->anisotropy != c.textureSampler.anisotropy) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy); + tex->anisotropy = c.textureSampler.anisotropy; } break; + } case GLRRenderCommand::TEXTURELOD: - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, c.textureLod.minLod); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod); + { + GLRTexture *tex = curTex[activeSlot]; + if (!tex) { + break; + } #ifndef USING_GLES2 - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias); + if (tex->lodBias != c.textureLod.lodBias) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias); + tex->lodBias = c.textureLod.lodBias; + } #endif + if (tex->minLod != c.textureLod.minLod) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, c.textureLod.minLod); + tex->minLod = c.textureLod.minLod; + } + if (tex->maxLod != c.textureLod.maxLod) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod); + tex->maxLod = c.textureLod.maxLod; + } break; + } case GLRRenderCommand::RASTER: if (c.raster.cullEnable) { if (!cullEnabled) { @@ -744,7 +784,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } } - if (activeTexture != 0) + if (activeSlot != 0) glActiveTexture(GL_TEXTURE0); // Wipe out the current state. diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index e712482ddf..6d0e44f0ca 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -111,9 +111,17 @@ public: glDeleteTextures(1, &texture); } } - GLuint texture; - GLenum target; - // TODO: Move sampler params here so we can move the dirty-tracking from TextureCacheGLES to here. + GLuint texture = 0; + // Could also trust OpenGL defaults I guess.. + GLenum target = 0xFFFF; + GLenum wrapS = 0xFFFF; + GLenum wrapT = 0xFFFF; + GLenum magFilter = 0xFFFF; + GLenum minFilter = 0xFFFF; + float anisotropy = -100000.0f; + float minLod = -100000.0f; + float maxLod = 100000.0f; + float lodBias = 0.0f; }; class GLRBuffer { From 7d6f9aec4d95f0eab2c37559a532dea0fd60c82d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 27 Dec 2017 14:46:01 +0100 Subject: [PATCH 034/291] iOS buildfix --- ext/native/thin3d/GLQueueRunner.cpp | 4 ++++ ext/native/thin3d/thin3d_gl.cpp | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 872d7b03dd..45e14ad164 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -9,6 +9,10 @@ #define TEXCACHE_NAME_CACHE_SIZE 16 +#ifdef IOS +extern void bindDefaultFBO(); +#endif + // Workaround for Retroarch. Simply declare // extern GLuint g_defaultFBO; // and set is as appropriate. Can adjust the variables in ext/native/base/display.h as diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index cf05ae4b75..22721ed468 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -16,10 +16,6 @@ #include "thin3d/GLRenderManager.h" -#ifdef IOS -extern void bindDefaultFBO(); -#endif - // #define DEBUG_READ_PIXELS 1 namespace Draw { From 422b05e51fd0a9742fe14c2e38819a232bdd41e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 10 Jan 2018 09:45:05 +0100 Subject: [PATCH 035/291] Truncate the '\n' from GL debug strings before logging them. --- Windows/GPU/WindowsGLContext.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 100814f5b0..b4c0692246 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -121,9 +121,16 @@ void DebugCallbackARB(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam) { (void)length; FILE *outFile = (FILE *)userParam; - char finalMessage[256]; - FormatDebugOutputARB(finalMessage, 256, source, type, id, severity, message); + char finalMessage[1024]; + FormatDebugOutputARB(finalMessage, sizeof(finalMessage), source, type, id, severity, message); OutputDebugStringA(finalMessage); + + // Truncate the \n before passing to our log functions. + size_t len = strlen(finalMessage); + if (len) { + finalMessage[len - 1] = '\0'; + } + switch (type) { case GL_DEBUG_TYPE_ERROR_ARB: case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: From 2656ad7d40d1c36254f08809dc570a0d1d43c521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 10 Jan 2018 10:17:42 +0100 Subject: [PATCH 036/291] Vulkan: Use push_back instead of resize(+1) --- Common/Vulkan/VulkanMemory.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Common/Vulkan/VulkanMemory.cpp b/Common/Vulkan/VulkanMemory.cpp index 721b97e5b5..1c4bfa68fb 100644 --- a/Common/Vulkan/VulkanMemory.cpp +++ b/Common/Vulkan/VulkanMemory.cpp @@ -75,9 +75,8 @@ bool VulkanPushBuffer::AddBuffer() { return false; } - buf_ = buffers_.size(); - buffers_.resize(buf_ + 1); // Why not push_back? - buffers_[buf_] = info; + buffers_.push_back(info); + buf_ = buffers_.size() - 1; return true; } From 465939e1c813163ccc3265a7a6534a3e24eb3f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 10 Jan 2018 10:18:18 +0100 Subject: [PATCH 037/291] Minor fixes, indentation and comments --- Windows/EmuThread.cpp | 6 +++--- ext/native/thin3d/GLQueueRunner.cpp | 8 ++++---- ext/native/thin3d/GLRenderManager.h | 4 ++-- ext/native/thin3d/thin3d_gl.cpp | 5 +++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 2617ed00c4..36dd44c34d 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -72,9 +72,9 @@ void EmuThread_Stop() { Core_Stop(); Core_WaitInactive(800); emuThread.join(); - if (useRenderThread) { - renderThread.join(); - } + if (useRenderThread) { + renderThread.join(); + } PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_UPDATE_UI, 0, 0); } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 45e14ad164..fd8286511a 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -134,13 +134,12 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { } } } - } break; + } case GLRInitStepType::CREATE_SHADER: { GLuint shader = glCreateShader(step.create_shader.stage); step.create_shader.shader->shader = shader; - // language_ = language; const char *code = step.create_shader.code; glShaderSource(shader, 1, &code, nullptr); delete[] code; @@ -667,7 +666,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } } attrMask = layout->semanticsMask_; - for (int i = 0; i < layout->entries.size(); i++) { + for (size_t i = 0; i < layout->entries.size(); i++) { auto &entry = layout->entries[i]; glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.bindVertexBuffer.offset + entry.offset)); } @@ -826,6 +825,7 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) { dstTex = dst->color_texture; break; case GL_DEPTH_BUFFER_BIT: + // TODO: Support depth copies. _assert_msg_(G3D, false, "Depth copies not yet supported - soon"); target = GL_RENDERBUFFER; /* @@ -1101,4 +1101,4 @@ GLRFramebuffer::~GLRFramebuffer() { } glDeleteTextures(1, &color_texture); -} \ No newline at end of file +} diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 6d0e44f0ca..22e5679258 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include @@ -101,7 +101,7 @@ public: } return loc; } - std::map uniformCache_; + std::unordered_map uniformCache_; }; class GLRTexture { diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 22721ed468..83ae2c484f 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -237,7 +237,7 @@ public: ~OpenGLShaderModule() { if (shader_) - render_->DeleteShader(shader_); + render_->DeleteShader(shader_); } bool Compile(GLRenderManager *render, ShaderLanguage language, const uint8_t *data, size_t dataSize); @@ -1036,7 +1036,8 @@ OpenGLInputLayout::~OpenGLInputLayout() { void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) { int semMask = 0; - // This is only accurate if there's only one stream. But whatever, for now. + // TODO: This is only accurate if there's only one stream. But whatever, for now we + // never use multiple streams anyway. stride = (GLsizei)desc.bindings[0].stride; std::vector entries; From b7f4f6e157f4b9b388c3be3916961b48c7b6d9f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 10 Jan 2018 10:48:46 +0100 Subject: [PATCH 038/291] GL render manager: Improve shader error reporting. --- GPU/GLES/DepalettizeShaderGLES.cpp | 4 ++-- GPU/GLES/FramebufferManagerGLES.cpp | 8 ++++---- GPU/GLES/ShaderManagerGLES.cpp | 13 ++++++++----- GPU/GLES/ShaderManagerGLES.h | 4 ++-- GPU/GLES/StencilBufferGLES.cpp | 4 ++-- ext/native/thin3d/GLQueueRunner.cpp | 18 ++++++++++++++---- ext/native/thin3d/GLQueueRunner.h | 2 ++ ext/native/thin3d/GLRenderManager.h | 6 +++++- ext/native/thin3d/thin3d_gl.cpp | 2 +- 9 files changed, 40 insertions(+), 21 deletions(-) diff --git a/GPU/GLES/DepalettizeShaderGLES.cpp b/GPU/GLES/DepalettizeShaderGLES.cpp index 95f58f37c6..bc3a84297f 100644 --- a/GPU/GLES/DepalettizeShaderGLES.cpp +++ b/GPU/GLES/DepalettizeShaderGLES.cpp @@ -72,7 +72,7 @@ DepalShaderCacheGLES::~DepalShaderCacheGLES() { bool DepalShaderCacheGLES::CreateVertexShader() { std::string src(useGL3_ ? depalVShader300 : depalVShader100); - vertexShader_ = render_->CreateShader(GL_VERTEX_SHADER, src); + vertexShader_ = render_->CreateShader(GL_VERTEX_SHADER, src, "depal"); return true; } @@ -154,7 +154,7 @@ DepalShader *DepalShaderCacheGLES::GetDepalettizeShader(uint32_t clutMode, GEBuf GenerateDepalShader(buffer, pixelFormat, useGL3_ ? GLSL_300 : GLSL_140); std::string src(buffer); - GLRShader *fragShader = render_->CreateShader(GL_FRAGMENT_SHADER, src); + GLRShader *fragShader = render_->CreateShader(GL_FRAGMENT_SHADER, src, "depal"); DepalShader *depal = new DepalShader(); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 7e117d3dda..67d9ce44cb 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -91,8 +91,8 @@ void FramebufferManagerGLES::CompileDraw2DProgram() { vs_code = ApplyGLSLPrelude(basic_vs, GL_VERTEX_SHADER); fs_code = ApplyGLSLPrelude(tex_fs, GL_FRAGMENT_SHADER); std::vector shaders; - shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vs_code)); - shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fs_code)); + shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vs_code, "draw2d")); + shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fs_code, "draw2d")); std::vector queries; queries.push_back({ &u_draw2d_tex, "u_tex" }); @@ -153,8 +153,8 @@ void FramebufferManagerGLES::CompilePostShader() { SetNumExtraFBOs(1); std::vector shaders; - shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vshader)); - shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, fshader)); + shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vshader, "postshader")); + shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, fshader, "postshader")); std::vector queries; queries.push_back({ &u_postShaderTex, "tex" }); queries.push_back({ &deltaLoc_, "u_texelDelta" }); diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 22d21f50d6..4c10e61527 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -44,11 +44,12 @@ #include "GPU/GLES/DrawEngineGLES.h" #include "FramebufferManagerGLES.h" -Shader::Shader(GLRenderManager *render, const char *code, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask) +Shader::Shader(GLRenderManager *render, const char *code, const char *desc, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask) : render_(render), failed_(false), useHWTransform_(useHWTransform), attrMask_(attrMask), uniformMask_(uniformMask) { PROFILE_THIS_SCOPE("shadercomp"); isFragment_ = glShaderType == GL_FRAGMENT_SHADER; source_ = code; + std::string descstr(desc); #ifdef SHADERLOG #ifdef _WIN32 OutputDebugStringUTF8(code); @@ -56,7 +57,7 @@ Shader::Shader(GLRenderManager *render, const char *code, uint32_t glShaderType, printf("%s\n", code); #endif #endif - shader = render->CreateShader(glShaderType, source_); + shader = render->CreateShader(glShaderType, source_, descstr); } Shader::~Shader() { @@ -608,7 +609,8 @@ Shader *ShaderManagerGLES::CompileFragmentShader(FShaderID FSID) { if (!GenerateFragmentShader(FSID, codeBuffer_, &uniformMask)) { return nullptr; } - return new Shader(render_, codeBuffer_, GL_FRAGMENT_SHADER, false, 0, uniformMask); + std::string desc = FragmentShaderDesc(FSID); + return new Shader(render_, codeBuffer_, desc.c_str(), GL_FRAGMENT_SHADER, false, 0, uniformMask); } Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { @@ -616,7 +618,8 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { uint32_t attrMask; uint64_t uniformMask; GenerateVertexShader(VSID, codeBuffer_, &attrMask, &uniformMask); - return new Shader(render_, codeBuffer_, GL_VERTEX_SHADER, useHWTransform, attrMask, uniformMask); + std::string desc = VertexShaderDesc(VSID); + return new Shader(render_, codeBuffer_, desc.c_str(), GL_VERTEX_SHADER, useHWTransform, attrMask, uniformMask); } Shader *ShaderManagerGLES::ApplyVertexShader(int prim, u32 vertType, VShaderID *VSID) { @@ -666,7 +669,7 @@ Shader *ShaderManagerGLES::ApplyVertexShader(int prim, u32 vertType, VShaderID * uint32_t attrMask; uint64_t uniformMask; GenerateVertexShader(vsidTemp, codeBuffer_, &attrMask, &uniformMask); - vs = new Shader(render_, codeBuffer_, GL_VERTEX_SHADER, false, attrMask, uniformMask); + vs = new Shader(render_, codeBuffer_, VertexShaderDesc(vsidTemp).c_str(), GL_VERTEX_SHADER, false, attrMask, uniformMask); } vsCache_.Insert(*VSID, vs); diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index 34ab88a7d8..b7ee34216b 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -125,12 +125,12 @@ public: class Shader { public: - Shader(GLRenderManager *render, const char *code, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask); + Shader(GLRenderManager *render, const char *code, const char *desc, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask); ~Shader(); GLRShader *shader; bool Failed() const { return failed_; } - bool UseHWTransform() const { return useHWTransform_; } // only relevant for vtx shaders + bool UseHWTransform() const { return useHWTransform_; } // only relevant for vtx shaders std::string GetShaderString(DebugShaderStringType type, ShaderID id) const; diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 1cd17c8c38..a2cd28166f 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -121,8 +121,8 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe vs_code = ApplyGLSLPrelude(stencil_vs, GL_VERTEX_SHADER); fs_code = ApplyGLSLPrelude(stencil_fs, GL_FRAGMENT_SHADER); std::vector shaders; - shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vs_code)); - shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fs_code)); + shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vs_code, "stencil")); + shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fs_code, "stencil")); std::vector queries; queries.push_back({ &u_stencilUploadTex, "tex" }); std::vector inits; diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index fd8286511a..c31bf38f4e 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -1,3 +1,4 @@ +#include "Core/Reporting.h" #include "GLQueueRunner.h" #include "GLRenderManager.h" #include "DataFormatGL.h" @@ -142,7 +143,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { step.create_shader.shader->shader = shader; const char *code = step.create_shader.code; glShaderSource(shader, 1, &code, nullptr); - delete[] code; + delete[] step.create_shader.code; glCompileShader(shader); GLint success = 0; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); @@ -152,11 +153,20 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { GLsizei len = 0; glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog); infoLog[len] = '\0'; - glDeleteShader(shader); - shader = 0; - ILOG("%s Shader compile error:\n%s", step.create_shader.stage == GL_FRAGMENT_SHADER ? "Fragment" : "Vertex", infoLog); +#ifdef __ANDROID__ + ELOG("Error in shader compilation! %s\n", infoLog); + ELOG("Shader source:\n%s\n", (const char *)code); +#endif + ERROR_LOG(G3D, "Error in shader compilation for: %s", step.create_shader.desc); + ERROR_LOG(G3D, "Info log: %s", infoLog); + ERROR_LOG(G3D, "Shader source:\n%s\n", (const char *)code); + Reporting::ReportMessage("Error in shader compilation: info: %s\n%s\n%s", infoLog, step.create_shader.desc, (const char *)code); +#ifdef SHADERLOG + OutputDebugStringUTF8(infoLog); +#endif step.create_shader.shader->valid = false; } + delete[] step.create_shader.desc; step.create_shader.shader->valid = true; break; } diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 6bea398557..f11e9fec44 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -193,7 +193,9 @@ struct GLRInitStep { } create_texture; struct { GLRShader *shader; + // These char arrays need to be allocated with new[]. char *code; + char *desc; // For error logging. GLuint stage; } create_shader; struct { diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 22e5679258..c351ed307a 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -218,12 +218,16 @@ public: return step.create_buffer.buffer; } - GLRShader *CreateShader(GLuint stage, std::string &code) { + GLRShader *CreateShader(GLuint stage, std::string code, std::string desc) { GLRInitStep step{ GLRInitStepType::CREATE_SHADER }; step.create_shader.shader = new GLRShader(); step.create_shader.stage = stage; step.create_shader.code = new char[code.size() + 1]; memcpy(step.create_shader.code, code.data(), code.size() + 1); + if (!desc.empty()) { + step.create_shader.desc = desc.size() ? new char[desc.size() + 1] : nullptr; + memcpy(step.create_shader.desc, desc.data(), desc.size() + 1); + } initSteps_.push_back(step); return step.create_shader.shader; } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 83ae2c484f..9df92b2c25 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -272,7 +272,7 @@ bool OpenGLShaderModule::Compile(GLRenderManager *render, ShaderLanguage languag source_ = temp.c_str(); } - shader_ = render->CreateShader(glstage_, source_); + shader_ = render->CreateShader(glstage_, source_, "thin3d"); return true; } From a642c1a990056970fa1d8e4262344c43d4808abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 10 Jan 2018 11:02:54 +0100 Subject: [PATCH 039/291] Fix goof with the stencil buffer drawing --- GPU/GLES/StencilBufferGLES.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index a2cd28166f..07eb171d89 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -178,13 +178,13 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe continue; } if (dstBuffer->format == GE_FORMAT_4444) { - render_->SetStencilOp((i << 4) | i, GL_KEEP, GL_KEEP, GL_KEEP); + render_->SetStencilOp((i << 4) | i, GL_REPLACE, GL_REPLACE, GL_REPLACE); render_->SetUniformF1(&u_stencilValue, i * (16.0f / 255.0f)); } else if (dstBuffer->format == GE_FORMAT_5551) { - render_->SetStencilOp(0xFF, GL_KEEP, GL_KEEP, GL_KEEP); + render_->SetStencilOp(0xFF, GL_REPLACE, GL_REPLACE, GL_REPLACE); render_->SetUniformF1(&u_stencilValue, i * (128.0f / 255.0f)); } else { - render_->SetStencilOp(i, GL_KEEP, GL_KEEP, GL_KEEP); + render_->SetStencilOp(i, GL_REPLACE, GL_REPLACE, GL_REPLACE); render_->SetUniformF1(&u_stencilValue, i * (1.0f / 255.0f)); } DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST); From 58854adb80a4d46469fe095f01ac5034e4dd395b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 10 Jan 2018 11:13:51 +0100 Subject: [PATCH 040/291] StencilBufferGLES: Move SetNoBlendAndMask to the right places. --- GPU/GLES/StencilBufferGLES.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 07eb171d89..33bea5daba 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -110,7 +110,9 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe } // Let's not bother with the shader if it's just zero. + render_->SetNoBlendAndMask(0x8); render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + render_->SetNoBlendAndMask(0xF); gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE); return true; } @@ -143,7 +145,6 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe shaderManagerGL_->DirtyLastShader(); DisableState(); - render_->SetNoBlendAndMask(0x8); bool useBlit = gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT); @@ -169,6 +170,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight, u1, v1); textureCacheGL_->ForgetLastTexture(); + render_->SetNoBlendAndMask(0x8); render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT); render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF); @@ -194,8 +196,8 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe draw_->BlitFramebuffer(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, Draw::FB_STENCIL_BIT, Draw::FB_BLIT_NEAREST); } + render_->SetNoBlendAndMask(0xF); gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); - RebindFramebuffer(); return true; } From d0038775e5436b5aaa29f3aff78e0945ec51d8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 10 Jan 2018 11:22:54 +0100 Subject: [PATCH 041/291] TODOs and indentations --- GPU/GLES/DrawEngineGLES.cpp | 1 + GPU/GLES/FramebufferManagerGLES.cpp | 4 ++-- GPU/GLES/StateMappingGLES.cpp | 1 + ext/native/thin3d/GLQueueRunner.cpp | 1 - 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index d6d803ed12..1aa3a0dd66 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -759,6 +759,7 @@ bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const { } void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) { + // TODO: Implement with the render manager /* #ifndef USING_GLES2 if (isAllowTexture1D_) { diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 67d9ce44cb..60bddd9499 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -293,8 +293,8 @@ void FramebufferManagerGLES::DestroyDeviceObjects() { } if (drawPixelsTex_) { render_->DeleteTexture(drawPixelsTex_); - drawPixelsTex_ = 0; - } + drawPixelsTex_ = 0; + } if (stencilUploadProgram_) { render_->DeleteProgram(stencilUploadProgram_); stencilUploadProgram_ = nullptr; diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index 1c8f52911d..0b9229e365 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -232,6 +232,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) { // TODO: Make this dynamic // Logic Ops if (gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_COPY) { + // TODO: Fix logic ops. //glstate.colorLogicOp.enable(); //glstate.logicOp.set(logicOps[gstate.getLogicOp()]); } else { diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index c31bf38f4e..8f63e76f38 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -398,7 +398,6 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { PerformBindFramebufferAsRenderTarget(step); - glDisable(GL_SCISSOR_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); From e4752a887f0f77abea9f4af9c991656dee721ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 10 Jan 2018 16:37:02 +0100 Subject: [PATCH 042/291] Fix use-after-free in shader error reporting --- ext/native/thin3d/GLQueueRunner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 8f63e76f38..4c3260e26e 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -143,7 +143,6 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { step.create_shader.shader->shader = shader; const char *code = step.create_shader.code; glShaderSource(shader, 1, &code, nullptr); - delete[] step.create_shader.code; glCompileShader(shader); GLint success = 0; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); @@ -166,6 +165,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { #endif step.create_shader.shader->valid = false; } + delete[] step.create_shader.code; delete[] step.create_shader.desc; step.create_shader.shader->valid = true; break; From af6431986d9f217a5d506177fecc34f634fa817a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Jan 2018 14:16:56 +0100 Subject: [PATCH 043/291] OpenGL: Now run GL on a secondary thread. Sync issues remain. --- Common/GraphicsContext.h | 5 +-- GPU/GLES/FramebufferManagerGLES.cpp | 1 - UI/EmuScreen.cpp | 2 +- Windows/EmuThread.cpp | 46 +++++++++++++++++++++------ Windows/GPU/WindowsGLContext.cpp | 26 +++++++++++---- Windows/GPU/WindowsGLContext.h | 11 ++++++- Windows/main.cpp | 4 ++- ext/native/thin3d/GLRenderManager.cpp | 27 ++++++++++------ ext/native/thin3d/GLRenderManager.h | 23 ++++++++++++-- 9 files changed, 110 insertions(+), 35 deletions(-) diff --git a/Common/GraphicsContext.h b/Common/GraphicsContext.h index e32dd6c306..64a5141379 100644 --- a/Common/GraphicsContext.h +++ b/Common/GraphicsContext.h @@ -10,10 +10,7 @@ class GraphicsContext { public: virtual ~GraphicsContext() {} - // Threaded backends (that need to do init on the final render thread, like GL) - // call this from the render thread. Init() should block until InitFromThread is done. - // Other backends can ignore this. - virtual bool InitFromThread() { return true; } + virtual bool InitFromRenderThread(std::string *errorMessage) { return true; } virtual void Shutdown() = 0; virtual void SwapInterval(int interval) = 0; diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 60bddd9499..21d0653e08 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -213,7 +213,6 @@ void FramebufferManagerGLES::CompilePostShader() { postShaderProgram_ = nullptr; usePostShader_ = false; } - glsl_unbind(); } void FramebufferManagerGLES::Bind2DShader() { diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 439aaf3444..1575109cd0 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -254,7 +254,7 @@ void EmuScreen::bootComplete() { #if !PPSSPP_PLATFORM(UWP) if (GetGPUBackend() == GPUBackend::OPENGL) { - const char *renderer = (const char*)glGetString(GL_RENDERER); + const char *renderer = gl_extensions.model; if (strstr(renderer, "Chainfire3D") != 0) { osm.Show(sc->T("Chainfire3DWarning", "WARNING: Chainfire3D detected, may cause problems"), 10.0f, 0xFF30a0FF, -1, true); } else if (strstr(renderer, "GLTools") != 0) { diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 36dd44c34d..7e5ed4f48f 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -33,6 +33,9 @@ static std::thread renderThread; static std::atomic renderThreadReady; static bool useRenderThread; +static bool renderThreadFailed; +static bool renderThreadSucceeded; +static std::string g_error_message; extern std::vector GetWideCmdLine(); @@ -85,15 +88,23 @@ bool EmuThread_Ready() { void RenderThreadFunc() { setCurrentThreadName("Render"); + renderThreadFailed = false; + renderThreadSucceeded = false; while (!g_graphicsContext) { - sleep_ms(50); + sleep_ms(10); continue; } - g_graphicsContext->InitFromThread(); - while (true) { - g_graphicsContext->ThreadFrame(); - break; + + std::string error_message; + if (!g_graphicsContext->InitFromRenderThread(&error_message)) { + g_error_message = error_message; + renderThreadFailed = true; + return; + } else { + renderThreadSucceeded = true; } + + g_graphicsContext->ThreadFrame(); } void EmuThreadFunc() { @@ -119,10 +130,25 @@ void EmuThreadFunc() { host->UpdateUI(); - GraphicsContext *graphicsContext = nullptr; - std::string error_string; - if (!host->InitGraphics(&error_string, &graphicsContext)) { + bool success = host->InitGraphics(&error_string, &g_graphicsContext); + + if (success) { + if (!useRenderThread) { + // This is also the render thread. + success = g_graphicsContext->InitFromRenderThread(&error_string); + } else { + while (!renderThreadFailed && !renderThreadSucceeded) { + sleep_ms(10); + } + success = renderThreadSucceeded; + if (!success) { + error_string = g_error_message; + } + } + } + + if (!success) { // Before anything: are we restarting right now? if (performingRestart) { // Okay, switching graphics didn't work out. Probably a driver bug - fallback to restart. @@ -171,7 +197,7 @@ void EmuThreadFunc() { exit(1); } - NativeInitGraphics(graphicsContext); + NativeInitGraphics(g_graphicsContext); NativeResized(); INFO_LOG(BOOT, "Done."); @@ -194,7 +220,7 @@ void EmuThreadFunc() { // This way they can load a new game. if (!Core_IsActive()) UpdateUIState(UISTATE_MENU); - Core_Run(graphicsContext); + Core_Run(g_graphicsContext); } shutdown: diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index b4c0692246..08bcc9a5b0 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -21,6 +21,7 @@ #include "gfx/gl_common.h" #include "gfx/gl_debug_log.h" #include "gfx_es2/gpu_features.h" +#include "thin3d/GLRenderManager.h" #include "GL/gl.h" #include "GL/wglew.h" #include "Core/Config.h" @@ -34,7 +35,8 @@ #include "Windows/GPU/WindowsGLContext.h" void WindowsGLContext::SwapBuffers() { - ::SwapBuffers(hDC); + renderManager_->Swap(); + // Used during fullscreen switching to prevent rendering. if (pauseRequested) { SetEvent(pauseEvent); @@ -151,10 +153,16 @@ void DebugCallbackARB(GLenum source, GLenum type, GLuint id, GLenum severity, } bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_message) { + hInst_ = hInst; + hWnd_ = window; + *error_message = "ok"; + return true; +} + +bool WindowsGLContext::InitFromRenderThread(std::string *error_message) { glslang::InitializeProcess(); *error_message = "ok"; - hWnd = window; GLuint PixelFormat; // TODO: Change to use WGL_ARB_pixel_format instead @@ -179,7 +187,7 @@ bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_mes 0, 0, 0 // Layer Masks Ignored }; - hDC = GetDC(hWnd); + hDC = GetDC(hWnd_); if (!hDC) { *error_message = "Failed to get a device context."; @@ -239,7 +247,7 @@ bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_mes std::wstring title = ConvertUTF8ToWString(err->T("OpenGLDriverError", "OpenGL driver error")); std::wstring combined = versionDetected + error; - bool yes = IDYES == MessageBox(hWnd, combined.c_str(), title.c_str(), MB_ICONERROR | MB_YESNO); + bool yes = IDYES == MessageBox(hWnd_, combined.c_str(), title.c_str(), MB_ICONERROR | MB_YESNO); if (yes) { // Change the config to D3D and restart. @@ -362,8 +370,10 @@ bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_mes CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); + renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); // if we get this far, there will always be a GLSL compiler capable of compiling these. + renderManager_->SetSwapFunction([&]() {::SwapBuffers(hDC); }); assert(success); CHECK_GL_ERROR_IF_DEBUG(); return true; // Success @@ -393,16 +403,20 @@ void WindowsGLContext::Shutdown() { hRC = NULL; } - if (hDC && !ReleaseDC(hWnd,hDC)) { + if (hDC && !ReleaseDC(hWnd_, hDC)) { DWORD err = GetLastError(); if (err != ERROR_DC_NOT_FOUND) { MessageBox(NULL, L"Release device context failed.", L"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); } hDC = NULL; } - hWnd = NULL; + hWnd_ = NULL; glslang::FinalizeProcess(); } void WindowsGLContext::Resize() { } + +void WindowsGLContext::ThreadFrame() { + renderManager_->ThreadFunc(); +} diff --git a/Windows/GPU/WindowsGLContext.h b/Windows/GPU/WindowsGLContext.h index 4ddd28ba61..b628ee25d2 100644 --- a/Windows/GPU/WindowsGLContext.h +++ b/Windows/GPU/WindowsGLContext.h @@ -7,10 +7,14 @@ namespace Draw { class DrawContext; } +class GLRenderManager; + class WindowsGLContext : public WindowsGraphicsContext { public: bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override; + bool InitFromRenderThread(std::string *errorMessage) override; + void Shutdown() override; void SwapInterval(int interval) override; void SwapBuffers() override; @@ -21,13 +25,18 @@ public: void Resume() override; void Resize() override; + void ThreadFrame() override; + Draw::DrawContext *GetDrawContext() override { return draw_; } private: + bool renderThread_; Draw::DrawContext *draw_; + GLRenderManager *renderManager_; + HINSTANCE hInst_; HDC hDC; // Private GDI Device Context HGLRC hRC; // Permanent Rendering Context - HWND hWnd; // Holds Our Window Handle + HWND hWnd_; // Holds Our Window Handle volatile bool pauseRequested; volatile bool resumeRequested; HANDLE pauseEvent; diff --git a/Windows/main.cpp b/Windows/main.cpp index 5bbe6ec01a..66c09110ba 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -530,7 +530,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin } // Emu thread (and render thread, if any) is always running! - EmuThread_Start(false); // g_Config.iGPUBackend == GPU_BACKEND_VULKAN); + // Only OpenGL uses an externally managed render thread (due to GL's single-threaded context design). Vulkan + // manages its own render thread. + EmuThread_Start(g_Config.iGPUBackend == (int)GPUBackend::OPENGL); InputDevice::BeginPolling(); HACCEL hAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_ACCELS); diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 452497d3e2..33d1be696f 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -44,7 +44,8 @@ GLRenderManager::GLRenderManager() { } if (!useThread_) { - queueRunner_.CreateDeviceObjects(); + // The main thread is also the render thread. + ThreadStartup(); } } @@ -54,16 +55,22 @@ GLRenderManager::~GLRenderManager() { } if (!useThread_) { - queueRunner_.DestroyDeviceObjects(); + // The main thread is also the render thread. + ThreadEnd(); } } -void GLRenderManager::ThreadFunc() { - setCurrentThreadName("RenderMan"); - int threadFrame = threadInitFrame_; - bool nextFrame = false; - bool firstFrame = true; +void GLRenderManager::ThreadStartup() { queueRunner_.CreateDeviceObjects(); +} + +void GLRenderManager::ThreadEnd() { + queueRunner_.DestroyDeviceObjects(); +} + +void GLRenderManager::ThreadFunc() { + ThreadStartup(); + int threadFrame = threadInitFrame_; while (true) { { if (nextFrame) { @@ -344,7 +351,9 @@ void GLRenderManager::EndSubmitFrame(int frame) { Submit(frame, true); if (!frameData.skipSwap) { - // glSwapBuffers(); + if (swapFunction_) { + swapFunction_(); + } } else { frameData.skipSwap = false; } @@ -540,4 +549,4 @@ size_t GLPushBuffer::GetTotalSize() const { sum += size_ * (buffers_.size() - 1); sum += offset_; return sum; -} \ No newline at end of file +} diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index c351ed307a..d6716f626b 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -622,7 +623,20 @@ public: frameData_[frame].activePushBuffers.erase(iter); } + void SetSwapFunction(std::function swapFunction) { + swapFunction_ = swapFunction; + } + + void Swap() { + if (!useThread_ && swapFunction_) { + swapFunction_(); + } + } + private: + void ThreadStartup(); + void ThreadEnd(); + void BeginSubmitFrame(int frame); void EndSubmitFrame(int frame); void Submit(int frame, bool triggerFence); @@ -668,17 +682,22 @@ private: // Execution time state bool run_ = true; - // Thread is managed elsewhere, and should call ThreadFunc. + // Thread is managed elsewhere, and should call ThreadFrame. std::mutex mutex_; int threadInitFrame_ = 0; GLQueueRunner queueRunner_; + bool nextFrame = false; + bool firstFrame = true; + GLDeleter deleter_; - bool useThread_ = false; + bool useThread_ = true; int curFrame_ = 0; + std::function swapFunction_; + int targetWidth_ = 0; int targetHeight_ = 0; }; From e5d571c25a3ef4854801d5a180267200f61c42d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Jan 2018 15:19:35 +0100 Subject: [PATCH 044/291] gl-render-manager: Now threaded mode seems to work fine (and fast!). Shutdown doesn't, though, and there are stability issues. --- Windows/GPU/WindowsGLContext.cpp | 2 +- ext/native/thin3d/GLQueueRunner.cpp | 4 +++- ext/native/thin3d/GLRenderManager.cpp | 6 +++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 08bcc9a5b0..f4285d017b 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -116,7 +116,7 @@ void FormatDebugOutputARB(char outStr[], size_t outStrSize, GLenum source, GLenu } snprintf(severityStr, sizeof(severityStr), severityFmt, severity); - snprintf(outStr, sizeof(outStr), "OpenGL: %s [source=%s type=%s severity=%s id=%d]\n", msg, sourceStr, typeStr, severityStr, id); + snprintf(outStr, outStrSize, "OpenGL: %s [source=%s type=%s severity=%s id=%d]\n", msg, sourceStr, typeStr, severityStr, id); } void DebugCallbackARB(GLenum source, GLenum type, GLuint id, GLenum severity, diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 4c3260e26e..ee4dfb2737 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -735,7 +735,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { tex->minFilter = c.textureSampler.minFilter; } if (tex->anisotropy != c.textureSampler.anisotropy) { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy); + if (c.textureSampler.anisotropy != 0.0f) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy); + } tex->anisotropy = c.textureSampler.anisotropy; } break; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 33d1be696f..b4c9535601 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -285,7 +285,7 @@ void GLRenderManager::BeginFrame() { } // vulkan_->BeginFrame(); - frameData.deleter.Perform(); + // In GL, we have to do deletes on the submission thread. insideFrame_ = true; } @@ -328,6 +328,10 @@ void GLRenderManager::BeginSubmitFrame(int frame) { if (!frameData.hasBegun) { frameData.hasBegun = true; } + + // This should be the best time to perform deletes for the next frame. + FrameData &nextFrameData = frameData_[(frame + 1) % MAX_INFLIGHT_FRAMES]; + nextFrameData.deleter.Perform(); } void GLRenderManager::Submit(int frame, bool triggerFence) { From 57615344e4e0d7c696de9a531fc504a9dba04131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Jan 2018 17:32:50 +0100 Subject: [PATCH 045/291] Fix for deletes, add some debugging stuff --- Common/Vulkan/VulkanContext.cpp | 32 +++++++++++----------- ext/native/thin3d/GLQueueRunner.cpp | 2 ++ ext/native/thin3d/GLRenderManager.cpp | 39 ++++++++++++++------------- ext/native/thin3d/GLRenderManager.h | 12 +++++++++ 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index 6f3cfb5d55..8854970e9d 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -1090,22 +1090,22 @@ const char *VulkanResultToString(VkResult res) { } void VulkanDeleteList::Take(VulkanDeleteList &del) { - assert(cmdPools_.size() == 0); - assert(descPools_.size() == 0); - assert(modules_.size() == 0); - assert(buffers_.size() == 0); - assert(bufferViews_.size() == 0); - assert(images_.size() == 0); - assert(imageViews_.size() == 0); - assert(deviceMemory_.size() == 0); - assert(samplers_.size() == 0); - assert(pipelines_.size() == 0); - assert(pipelineCaches_.size() == 0); - assert(renderPasses_.size() == 0); - assert(framebuffers_.size() == 0); - assert(pipelineLayouts_.size() == 0); - assert(descSetLayouts_.size() == 0); - assert(callbacks_.size() == 0); + assert(cmdPools_.empty()); + assert(descPools_.empty()); + assert(modules_.empty()); + assert(buffers_.empty()); + assert(bufferViews_.empty()); + assert(images_.empty()); + assert(imageViews_.empty()); + assert(deviceMemory_.empty()); + assert(samplers_.empty()); + assert(pipelines_.empty()); + assert(pipelineCaches_.empty()); + assert(renderPasses_.empty()); + assert(framebuffers_.empty()); + assert(pipelineLayouts_.empty()); + assert(descSetLayouts_.empty()); + assert(callbacks_.empty()); cmdPools_ = std::move(del.cmdPools_); descPools_ = std::move(del.descPools_); modules_ = std::move(del.modules_); diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index ee4dfb2737..4b6bedada7 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -187,6 +187,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { case GLRInitStepType::TEXTURE_IMAGE: { GLRTexture *tex = step.texture_image.texture; + _assert_msg_(G3D, tex->canary == GLRTexture::CanaryValue, "Canary has bad value %08x in texture %p", tex->canary, tex); CHECK_GL_ERROR_IF_DEBUG(); if (boundTexture != tex->texture) { glBindTexture(tex->target, tex->texture); @@ -624,6 +625,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } if (c.texture.texture) { if (curTex[slot] != c.texture.texture) { + _assert_msg_(G3D, c.texture.texture->canary == GLRTexture::CanaryValue, "Canary has bad value %08x in texture %p", c.texture.texture->canary, c.texture.texture); glBindTexture(c.texture.texture->target, c.texture.texture->texture); curTex[slot] = c.texture.texture; } diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index b4c9535601..d4532489c9 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -12,6 +12,7 @@ #endif void GLDeleter::Perform() { + deleterMutex_.lock(); for (auto shader : shaders) { delete shader; } @@ -36,6 +37,7 @@ void GLDeleter::Perform() { delete framebuffer; } framebuffers.clear(); + deleterMutex_.unlock(); } GLRenderManager::GLRenderManager() { @@ -62,6 +64,7 @@ GLRenderManager::~GLRenderManager() { void GLRenderManager::ThreadStartup() { queueRunner_.CreateDeviceObjects(); + threadFrame_ = threadInitFrame_; } void GLRenderManager::ThreadEnd() { @@ -70,25 +73,24 @@ void GLRenderManager::ThreadEnd() { void GLRenderManager::ThreadFunc() { ThreadStartup(); - int threadFrame = threadInitFrame_; while (true) { { if (nextFrame) { - threadFrame++; - if (threadFrame >= MAX_INFLIGHT_FRAMES) - threadFrame = 0; + threadFrame_++; + if (threadFrame_ >= MAX_INFLIGHT_FRAMES) + threadFrame_ = 0; } - FrameData &frameData = frameData_[threadFrame]; + FrameData &frameData = frameData_[threadFrame_]; std::unique_lock lock(frameData.pull_mutex); while (!frameData.readyForRun && run_) { - VLOG("PULL: Waiting for frame[%d].readyForRun", threadFrame); + VLOG("PULL: Waiting for frame[%d].readyForRun", threadFrame_); frameData.pull_condVar.wait(lock); } if (!frameData.readyForRun && !run_) { // This means we're out of frames to render and run_ is false, so bail. break; } - VLOG("PULL: frame[%d].readyForRun = false", threadFrame); + VLOG("PULL: frame[%d].readyForRun = false", threadFrame_); frameData.readyForRun = false; // Previously we had a quick exit here that avoided calling Run() if run_ was suddenly false, // but that created a race condition where frames could end up not finished properly on resize etc. @@ -97,15 +99,15 @@ void GLRenderManager::ThreadFunc() { nextFrame = frameData.type == GLRRunType::END; assert(frameData.type == GLRRunType::END || frameData.type == GLRRunType::SYNC); } - VLOG("PULL: Running frame %d", threadFrame); + VLOG("PULL: Running frame %d", threadFrame_); if (firstFrame) { - ILOG("Running first frame (%d)", threadFrame); + ILOG("Running first frame (%d)", threadFrame_); firstFrame = false; } - Run(threadFrame); - VLOG("PULL: Finished frame %d", threadFrame); + Run(threadFrame_); + VLOG("PULL: Finished frame %d", threadFrame_); } - queueRunner_.DestroyDeviceObjects(); + ThreadEnd(); VLOG("PULL: Quitting"); } @@ -113,7 +115,6 @@ void GLRenderManager::ThreadFunc() { void GLRenderManager::StopThread() { // Since we don't control the thread directly, this will only pause the thread. - if (useThread_ && run_) { run_ = false; for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { @@ -274,6 +275,7 @@ void GLRenderManager::BeginFrame() { VLOG("PUSH: Fencing %d", curFrame); + // vkWaitForFences(device, 1, &frameData.fence, true, UINT64_MAX); // vkResetFences(device, 1, &frameData.fence); // glFenceSync(...) @@ -313,7 +315,6 @@ void GLRenderManager::Finish() { frameData.pull_condVar.notify_all(); } - // vulkan_->EndFrame(); frameData_[curFrame_].deleter.Take(deleter_); curFrame_++; @@ -328,10 +329,6 @@ void GLRenderManager::BeginSubmitFrame(int frame) { if (!frameData.hasBegun) { frameData.hasBegun = true; } - - // This should be the best time to perform deletes for the next frame. - FrameData &nextFrameData = frameData_[(frame + 1) % MAX_INFLIGHT_FRAMES]; - nextFrameData.deleter.Perform(); } void GLRenderManager::Submit(int frame, bool triggerFence) { @@ -340,8 +337,14 @@ void GLRenderManager::Submit(int frame, bool triggerFence) { // In GL, submission happens automatically in Run(). // When !triggerFence, we notify after syncing with Vulkan. + + // Putting deletes here is safe but only because OpenGL has its own delete handling.. + // ideally we'd like to wait a frame or two. + frameData.deleter.Perform(); + if (useThread_ && triggerFence) { VLOG("PULL: Frame %d.readyForFence = true", frame); + std::unique_lock lock(frameData.push_mutex); frameData.readyForFence = true; frameData.push_condVar.notify_all(); diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index d6716f626b..dd8b3b29c5 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -111,7 +111,12 @@ public: if (texture) { glDeleteTextures(1, &texture); } + canary = 0xd31373d; // deleted } + enum { + CanaryValue = 0x12345678, + }; + uint32_t canary = CanaryValue; GLuint texture = 0; // Could also trust OpenGL defaults I guess.. GLenum target = 0xFFFF; @@ -149,6 +154,8 @@ public: void Perform(); void Take(GLDeleter &other) { + deleterMutex_.lock(); + _assert_msg_(G3D, shaders.empty() && programs.empty() && buffers.empty() && textures.empty() && inputLayouts.empty() && framebuffers.empty(), "Deleter already has stuff"); shaders = std::move(other.shaders); programs = std::move(other.programs); buffers = std::move(other.buffers); @@ -161,6 +168,7 @@ public: other.textures.clear(); other.inputLayouts.clear(); other.framebuffers.clear(); + deleterMutex_.unlock(); } std::vector shaders; @@ -169,6 +177,7 @@ public: std::vector textures; std::vector inputLayouts; std::vector framebuffers; + std::mutex deleterMutex_; }; class GLRInputLayout { @@ -687,6 +696,9 @@ private: int threadInitFrame_ = 0; GLQueueRunner queueRunner_; + // Thread state + int threadFrame_; + bool nextFrame = false; bool firstFrame = true; From fdca06d20813c8eeb15e19d03a90f104ac061a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Jan 2018 18:13:31 +0100 Subject: [PATCH 046/291] More work on shutdown, still hanging though. --- Common/GraphicsContext.h | 5 +- Windows/EmuThread.cpp | 10 +++- Windows/GPU/WindowsGLContext.cpp | 21 ++++++-- Windows/GPU/WindowsGLContext.h | 5 +- android/jni/app-android.cpp | 1 - ext/native/thin3d/GLRenderManager.cpp | 74 +++++++++++++-------------- ext/native/thin3d/GLRenderManager.h | 11 ++-- 7 files changed, 73 insertions(+), 54 deletions(-) diff --git a/Common/GraphicsContext.h b/Common/GraphicsContext.h index 64a5141379..66afcd94da 100644 --- a/Common/GraphicsContext.h +++ b/Common/GraphicsContext.h @@ -11,6 +11,7 @@ public: virtual ~GraphicsContext() {} virtual bool InitFromRenderThread(std::string *errorMessage) { return true; } + virtual void ShutdownFromRenderThread() {} virtual void Shutdown() = 0; virtual void SwapInterval(int interval) = 0; @@ -28,7 +29,9 @@ public: virtual void *GetAPIContext() { return nullptr; } // Called from the render thread from threaded backends. - virtual void ThreadFrame() {} + virtual void ThreadStart() {} + virtual bool ThreadFrame() { return true; } + virtual void ThreadEnd() {} virtual Draw::DrawContext *GetDrawContext() = 0; }; diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 7e5ed4f48f..da187068d6 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -104,7 +104,13 @@ void RenderThreadFunc() { renderThreadSucceeded = true; } - g_graphicsContext->ThreadFrame(); + g_graphicsContext->ThreadStart(); + while (emuThreadState != THREAD_SHUTDOWN) { + if (!g_graphicsContext->ThreadFrame()) + break; + } + g_graphicsContext->ThreadEnd(); + g_graphicsContext->ShutdownFromRenderThread(); } void EmuThreadFunc() { @@ -227,6 +233,8 @@ shutdown: emuThreadState = THREAD_SHUTDOWN; NativeShutdownGraphics(); + if (!useRenderThread) + g_graphicsContext->ShutdownFromRenderThread(); // NativeShutdown deletes the graphics context through host->ShutdownGraphics(). NativeShutdown(); diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index f4285d017b..ac48df35fd 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -153,6 +153,8 @@ void DebugCallbackARB(GLenum source, GLenum type, GLuint id, GLenum severity, } bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_message) { + glslang::InitializeProcess(); + hInst_ = hInst; hWnd_ = window; *error_message = "ok"; @@ -160,8 +162,6 @@ bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_mes } bool WindowsGLContext::InitFromRenderThread(std::string *error_message) { - glslang::InitializeProcess(); - *error_message = "ok"; GLuint PixelFormat; @@ -386,6 +386,10 @@ void WindowsGLContext::SwapInterval(int interval) { } void WindowsGLContext::Shutdown() { + glslang::FinalizeProcess(); +} + +void WindowsGLContext::ShutdownFromRenderThread() { delete draw_; draw_ = nullptr; CloseHandle(pauseEvent); @@ -411,12 +415,19 @@ void WindowsGLContext::Shutdown() { hDC = NULL; } hWnd_ = NULL; - glslang::FinalizeProcess(); } void WindowsGLContext::Resize() { } -void WindowsGLContext::ThreadFrame() { - renderManager_->ThreadFunc(); +void WindowsGLContext::ThreadStart() { + renderManager_->ThreadStart(); +} + +bool WindowsGLContext::ThreadFrame() { + return renderManager_->ThreadFrame(); +} + +void WindowsGLContext::ThreadEnd() { + renderManager_->ThreadEnd(); } diff --git a/Windows/GPU/WindowsGLContext.h b/Windows/GPU/WindowsGLContext.h index b628ee25d2..38c9494947 100644 --- a/Windows/GPU/WindowsGLContext.h +++ b/Windows/GPU/WindowsGLContext.h @@ -14,6 +14,7 @@ public: bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override; bool InitFromRenderThread(std::string *errorMessage) override; + void ShutdownFromRenderThread() override; void Shutdown() override; void SwapInterval(int interval) override; @@ -25,7 +26,9 @@ public: void Resume() override; void Resize() override; - void ThreadFrame() override; + void ThreadStart() override; + void ThreadEnd() override; + bool ThreadFrame() override; Draw::DrawContext *GetDrawContext() override { return draw_; } diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 48fe18013c..97ce69edc4 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -470,7 +470,6 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv } } - // JavaEGL extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { static bool hasSetThreadName = false; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index d4532489c9..85cd8b5089 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -47,7 +47,7 @@ GLRenderManager::GLRenderManager() { if (!useThread_) { // The main thread is also the render thread. - ThreadStartup(); + ThreadStart(); } } @@ -62,54 +62,50 @@ GLRenderManager::~GLRenderManager() { } } -void GLRenderManager::ThreadStartup() { +void GLRenderManager::ThreadStart() { queueRunner_.CreateDeviceObjects(); threadFrame_ = threadInitFrame_; } void GLRenderManager::ThreadEnd() { queueRunner_.DestroyDeviceObjects(); + VLOG("PULL: Quitting"); } -void GLRenderManager::ThreadFunc() { - ThreadStartup(); - while (true) { - { - if (nextFrame) { - threadFrame_++; - if (threadFrame_ >= MAX_INFLIGHT_FRAMES) - threadFrame_ = 0; - } - FrameData &frameData = frameData_[threadFrame_]; - std::unique_lock lock(frameData.pull_mutex); - while (!frameData.readyForRun && run_) { - VLOG("PULL: Waiting for frame[%d].readyForRun", threadFrame_); - frameData.pull_condVar.wait(lock); - } - if (!frameData.readyForRun && !run_) { - // This means we're out of frames to render and run_ is false, so bail. - break; - } - VLOG("PULL: frame[%d].readyForRun = false", threadFrame_); - frameData.readyForRun = false; - // Previously we had a quick exit here that avoided calling Run() if run_ was suddenly false, - // but that created a race condition where frames could end up not finished properly on resize etc. +bool GLRenderManager::ThreadFrame() { + { + if (nextFrame) { + threadFrame_++; + if (threadFrame_ >= MAX_INFLIGHT_FRAMES) + threadFrame_ = 0; + } + FrameData &frameData = frameData_[threadFrame_]; + std::unique_lock lock(frameData.pull_mutex); + while (!frameData.readyForRun && run_) { + VLOG("PULL: Waiting for frame[%d].readyForRun", threadFrame_); + frameData.pull_condVar.wait(lock); + } + if (!frameData.readyForRun && !run_) { + // This means we're out of frames to render and run_ is false, so bail. + return false; + } + VLOG("PULL: frame[%d].readyForRun = false", threadFrame_); + frameData.readyForRun = false; + // Previously we had a quick exit here that avoided calling Run() if run_ was suddenly false, + // but that created a race condition where frames could end up not finished properly on resize etc. - // Only increment next time if we're done. - nextFrame = frameData.type == GLRRunType::END; - assert(frameData.type == GLRRunType::END || frameData.type == GLRRunType::SYNC); - } - VLOG("PULL: Running frame %d", threadFrame_); - if (firstFrame) { - ILOG("Running first frame (%d)", threadFrame_); - firstFrame = false; - } - Run(threadFrame_); - VLOG("PULL: Finished frame %d", threadFrame_); + // Only increment next time if we're done. + nextFrame = frameData.type == GLRRunType::END; + assert(frameData.type == GLRRunType::END || frameData.type == GLRRunType::SYNC); } - ThreadEnd(); - - VLOG("PULL: Quitting"); + VLOG("PULL: Running frame %d", threadFrame_); + if (firstFrame) { + ILOG("Running first frame (%d)", threadFrame_); + firstFrame = false; + } + Run(threadFrame_); + VLOG("PULL: Finished frame %d", threadFrame_); + return true; } void GLRenderManager::StopThread() { diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index dd8b3b29c5..0778f35339 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -199,7 +199,9 @@ public: GLRenderManager(); ~GLRenderManager(); - void ThreadFunc(); + void ThreadStart(); + void ThreadEnd(); + bool ThreadFrame(); // Returns false to request exiting the loop. // Makes sure that the GPU has caught up enough that we can start writing buffers of this frame again. void BeginFrame(); @@ -642,10 +644,9 @@ public: } } -private: - void ThreadStartup(); - void ThreadEnd(); + void StopThread(); +private: void BeginSubmitFrame(int frame); void EndSubmitFrame(int frame); void Submit(int frame, bool triggerFence); @@ -654,8 +655,6 @@ private: void FlushSync(); void EndSyncFrame(int frame); - void StopThread(); - // Per-frame data, round-robin so we can overlap submission with execution of the previous frame. struct FrameData { std::mutex push_mutex; From 4f1b8d80a9c55071d12a83876f34fed2cf861afb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 18 Jan 2018 21:13:30 -0800 Subject: [PATCH 047/291] GLES: Bind texture on MakePixelTexture(). This is currently necessary because callers expect it. Also, move inside render passes. --- GPU/Common/FramebufferCommon.cpp | 4 ++-- GPU/GLES/FramebufferManagerGLES.cpp | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index c0d747802f..718500058b 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -719,8 +719,6 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int float u0 = 0.0f, u1 = 1.0f; float v0 = 0.0f, v1 = 1.0f; - MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height, u1, v1); - if (useBufferedRendering_ && vfb && vfb->fbo) { draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }); SetViewport2D(0, 0, vfb->renderWidth, vfb->renderHeight); @@ -736,6 +734,8 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int } DisableState(); + MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height, u1, v1); + DrawTextureFlags flags = (vfb || g_Config.iBufFilter == SCALE_LINEAR) ? DRAWTEX_LINEAR : DRAWTEX_NEAREST; Bind2DShader(); DrawActiveTexture(dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, u0, v0, u1, v1, ROTATION_LOCKED_HORIZONTAL, flags); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 21d0653e08..711c97b398 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -372,6 +372,9 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma } render_->TextureImage(drawPixelsTex_, 0, texWidth, height, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, convBuf, false); render_->FinalizeTexture(drawPixelsTex_, 0, false); + + // TODO: Return instead? + render_->BindTexture(0, drawPixelsTex_); } void FramebufferManagerGLES::SetViewport2D(int x, int y, int w, int h) { From a135035850d0e6fc4d9378196ae8a026167ee99b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 18 Jan 2018 21:14:17 -0800 Subject: [PATCH 048/291] GLES: Ensure stencil upload clear in render pass. Fixes crashes in Star Ocean. --- GPU/GLES/StencilBufferGLES.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 33bea5daba..05965b9c59 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -110,6 +110,9 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe } // Let's not bother with the shader if it's just zero. + if (dstBuffer->fbo) { + draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }); + } render_->SetNoBlendAndMask(0x8); render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); render_->SetNoBlendAndMask(0xF); From 790e3121d2d0ff12fde4788561ae372c059ddc3e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 18 Jan 2018 21:15:21 -0800 Subject: [PATCH 049/291] GLES: Move stencil upload state into render pass. Without this, stencil upload simply failed silently. Fixes Star Ocean stencil issues. --- GPU/GLES/StencilBufferGLES.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 05965b9c59..4345f1b14f 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -130,6 +130,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fs_code, "stencil")); std::vector queries; queries.push_back({ &u_stencilUploadTex, "tex" }); + queries.push_back({ &u_stencilValue, "u_stencilValue" }); std::vector inits; inits.push_back({ &u_stencilUploadTex, 0, 0 }); stencilUploadProgram_ = render_->CreateProgram(shaders, {}, queries, inits, false); @@ -138,11 +139,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe } if (!stencilUploadProgram_) { ERROR_LOG_REPORT(G3D, "Failed to compile stencilUploadProgram! This shouldn't happen.\n%s", errorString.c_str()); - } else { - render_->BindProgram(stencilUploadProgram_); } - } else { - render_->BindProgram(stencilUploadProgram_); } shaderManagerGL_->DirtyLastShader(); @@ -173,9 +170,11 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight, u1, v1); textureCacheGL_->ForgetLastTexture(); - render_->SetNoBlendAndMask(0x8); + // We must bind the program after starting the render pass, and set the color mask after clearing. render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT); render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF); + render_->BindProgram(stencilUploadProgram_); + render_->SetNoBlendAndMask(0x8); for (int i = 1; i < values; i += i) { if (!(usedBits & i)) { From 22bf124631e85fccfcc01989b9523981116ef052 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 18 Jan 2018 21:16:06 -0800 Subject: [PATCH 050/291] GLES: Document stencil clearing bug. --- GPU/GLES/StencilBufferGLES.cpp | 1 + ext/native/thin3d/GLQueueRunner.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 4345f1b14f..980c3d4406 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -113,6 +113,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe if (dstBuffer->fbo) { draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }); } + // TODO: This incorrectly does not apply to the clear currently. render_->SetNoBlendAndMask(0x8); render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); render_->SetNoBlendAndMask(0xF); diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 4b6bedada7..0434a997f8 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -498,6 +498,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { break; case GLRRenderCommand::CLEAR: glDisable(GL_SCISSOR_TEST); + // TODO: We sometimes pass a color mask in that we want to respect (StencilBufferGLES.) + // We want to clear to only clear alpha, in that case. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); colorMask = 0xF; if (c.clear.clearMask & GL_COLOR_BUFFER_BIT) { From 3eb6d38d75332d7dd23a9602aa06dffca936ccf7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 18 Jan 2018 21:34:52 -0800 Subject: [PATCH 051/291] Vulkan: Fix stencil-only clear for stencil upload. Fixes stencil issues in Star Ocean. --- GPU/Vulkan/StencilBufferVulkan.cpp | 15 ++++++++------- ext/native/thin3d/GLRenderManager.cpp | 9 ++++++--- ext/native/thin3d/GLRenderManager.h | 2 +- ext/native/thin3d/VulkanQueueRunner.cpp | 6 +++--- ext/native/thin3d/VulkanQueueRunner.h | 3 ++- ext/native/thin3d/VulkanRenderManager.cpp | 12 +++++++----- ext/native/thin3d/VulkanRenderManager.h | 2 +- ext/native/thin3d/thin3d_gl.cpp | 3 ++- ext/native/thin3d/thin3d_vulkan.cpp | 3 ++- 9 files changed, 32 insertions(+), 23 deletions(-) diff --git a/GPU/Vulkan/StencilBufferVulkan.cpp b/GPU/Vulkan/StencilBufferVulkan.cpp index 8ee4666583..cb873765f1 100644 --- a/GPU/Vulkan/StencilBufferVulkan.cpp +++ b/GPU/Vulkan/StencilBufferVulkan.cpp @@ -155,21 +155,22 @@ bool FramebufferManagerVulkan::NotifyStencilUpload(u32 addr, int size, bool skip // It's already zero, let's skip it. continue; } - // These feel a little backwards : Mask is the bits that are going to be written, while value - // is the "mask" that will be tested against. - uint8_t mask = 0; + + // These are the stencil bits that will be written. We discard when the bit doesn't match. + uint8_t writeMask = 0; + // This is the value to test the texture alpha against in the shader. uint32_t value = 0; if (dstBuffer->format == GE_FORMAT_4444) { - mask = i | (i << 4); + writeMask = i | (i << 4); value = i * 16; } else if (dstBuffer->format == GE_FORMAT_5551) { - mask = 0xFF; + writeMask = 0xFF; value = i * 128; } else { - mask = i; + writeMask = i; value = i; } - renderManager->SetStencilParams(mask, 0xFF, 0xFF); + renderManager->SetStencilParams(writeMask, 0xFF, 0xFF); // Need to specify both VERTEX and FRAGMENT bits here since that's what we set up in the pipeline layout, and we need // that for the post shaders. There's probably not really a cost to this. renderManager->PushConstants(vulkan2D_->GetPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4, &value); diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 85cd8b5089..3cbc3a2dd8 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -157,11 +157,11 @@ void GLRenderManager::StopThread() { } } -void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil) { +void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, GLRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil) { assert(insideFrame_); // Eliminate dupes. if (steps_.size() && steps_.back()->render.framebuffer == fb && steps_.back()->stepType == GLRStepType::RENDER) { - if (color != GLRRenderPassAction::CLEAR && depth != GLRRenderPassAction::CLEAR) { + if (color != GLRRenderPassAction::CLEAR && depth != GLRRenderPassAction::CLEAR && stencil != GLRRenderPassAction::CLEAR) { // We don't move to a new step, this bind was unnecessary and we can safely skip it. return; } @@ -184,8 +184,11 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende data.clear.clearColor = clearColor; } if (depth == GLRRenderPassAction::CLEAR) { - clearMask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; + clearMask |= GL_DEPTH_BUFFER_BIT; data.clear.clearZ = clearDepth; + } + if (stencil == GLRRenderPassAction::CLEAR) { + clearMask |= GL_STENCIL_BUFFER_BIT; data.clear.clearStencil = clearStencil; } if (clearMask) { diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 0778f35339..711aa143fb 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -310,7 +310,7 @@ public: deleter_.framebuffers.push_back(framebuffer); } - void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil); + void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, GLRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil); void BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment); bool CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride); void CopyImageToMemorySync(GLuint texture, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride); diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index e693dc834a..5cd4008386 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -391,7 +391,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c } // Don't execute empty renderpasses. - if (step.commands.empty() && step.render.color == VKRRenderPassAction::KEEP && step.render.depthStencil == VKRRenderPassAction::KEEP) { + if (step.commands.empty() && step.render.color == VKRRenderPassAction::KEEP && step.render.depth == VKRRenderPassAction::KEEP && step.render.stencil == VKRRenderPassAction::KEEP) { // Nothing to do. return; } @@ -610,12 +610,12 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step fb->depth.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; } - renderPass = GetRenderPass(step.render.color, step.render.depthStencil, step.render.depthStencil); + renderPass = GetRenderPass(step.render.color, step.render.depth, step.render.stencil); if (step.render.color == VKRRenderPassAction::CLEAR) { Uint8x4ToFloat4(clearVal[0].color.float32, step.render.clearColor); numClearVals = 1; } - if (step.render.depthStencil == VKRRenderPassAction::CLEAR) { + if (step.render.depth == VKRRenderPassAction::CLEAR || step.render.stencil == VKRRenderPassAction::CLEAR) { clearVal[1].depthStencil.depth = step.render.clearDepth; clearVal[1].depthStencil.stencil = step.render.clearStencil; numClearVals = 2; diff --git a/ext/native/thin3d/VulkanQueueRunner.h b/ext/native/thin3d/VulkanQueueRunner.h index 1049a5bb80..b52b150fa3 100644 --- a/ext/native/thin3d/VulkanQueueRunner.h +++ b/ext/native/thin3d/VulkanQueueRunner.h @@ -108,7 +108,8 @@ struct VKRStep { struct { VKRFramebuffer *framebuffer; VKRRenderPassAction color; - VKRRenderPassAction depthStencil; + VKRRenderPassAction depth; + VKRRenderPassAction stencil; uint32_t clearColor; float clearDepth; int clearStencil; diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index ab9bbafc22..ef262e9dc1 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -389,16 +389,16 @@ VkCommandBuffer VulkanRenderManager::GetInitCmd() { return frameData_[curFrame].initCmd; } -void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassAction color, VKRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil) { +void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassAction color, VKRRenderPassAction depth, VKRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil) { assert(insideFrame_); // Eliminate dupes. if (steps_.size() && steps_.back()->render.framebuffer == fb && steps_.back()->stepType == VKRStepType::RENDER) { - if (color != VKRRenderPassAction::CLEAR && depth != VKRRenderPassAction::CLEAR) { + if (color != VKRRenderPassAction::CLEAR && depth != VKRRenderPassAction::CLEAR && stencil != VKRRenderPassAction::CLEAR) { // We don't move to a new step, this bind was unnecessary and we can safely skip it. return; } } - if (curRenderStep_ && curRenderStep_->commands.size() == 0 && curRenderStep_->render.color == VKRRenderPassAction::KEEP && curRenderStep_->render.depthStencil == VKRRenderPassAction::KEEP) { + if (curRenderStep_ && curRenderStep_->commands.size() == 0 && curRenderStep_->render.color == VKRRenderPassAction::KEEP && curRenderStep_->render.depth == VKRRenderPassAction::KEEP && curRenderStep_->render.stencil == VKRRenderPassAction::KEEP) { // Can trivially kill the last empty render step. assert(steps_.back() == curRenderStep_); delete steps_.back(); @@ -413,7 +413,8 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR // This is what queues up new passes, and can end previous ones. step->render.framebuffer = fb; step->render.color = color; - step->render.depthStencil = depth; + step->render.depth= depth; + step->render.stencil = stencil; step->render.clearColor = clearColor; step->render.clearDepth = clearDepth; step->render.clearStencil = clearStencil; @@ -617,7 +618,8 @@ void VulkanRenderManager::Clear(uint32_t clearColor, float clearZ, int clearSten curRenderStep_->render.clearDepth = clearZ; curRenderStep_->render.clearStencil = clearStencil; curRenderStep_->render.color = (clearMask & VK_IMAGE_ASPECT_COLOR_BIT) ? VKRRenderPassAction::CLEAR : VKRRenderPassAction::KEEP; - curRenderStep_->render.depthStencil = (clearMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) ? VKRRenderPassAction::CLEAR : VKRRenderPassAction::KEEP; + curRenderStep_->render.depth = (clearMask & VK_IMAGE_ASPECT_DEPTH_BIT) ? VKRRenderPassAction::CLEAR : VKRRenderPassAction::KEEP; + curRenderStep_->render.stencil = (clearMask & VK_IMAGE_ASPECT_STENCIL_BIT) ? VKRRenderPassAction::CLEAR : VKRRenderPassAction::KEEP; } else { VkRenderData data{ VKRRenderCommand::CLEAR }; data.clear.clearColor = clearColor; diff --git a/ext/native/thin3d/VulkanRenderManager.h b/ext/native/thin3d/VulkanRenderManager.h index b074e3b4f9..d97ebf42ca 100644 --- a/ext/native/thin3d/VulkanRenderManager.h +++ b/ext/native/thin3d/VulkanRenderManager.h @@ -99,7 +99,7 @@ public: // Zaps queued up commands. Use if you know there's a risk you've queued up stuff that has already been deleted. Can happen during in-game shutdown. void Wipe(); - void BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassAction color, VKRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil); + void BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassAction color, VKRRenderPassAction depth, VKRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil); VkImageView BindFramebufferAsTexture(VKRFramebuffer *fb, int binding, int aspectBit, int attachment); bool CopyFramebufferToMemorySync(VKRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride); void CopyImageToMemorySync(VkImage image, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride); diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 9df92b2c25..82d66dd0e1 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -1090,8 +1090,9 @@ void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const Render OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; GLRRenderPassAction color = (GLRRenderPassAction)rp.color; GLRRenderPassAction depth = (GLRRenderPassAction)rp.depth; + GLRRenderPassAction stencil = (GLRRenderPassAction)rp.stencil; - renderManager_.BindFramebufferAsRenderTarget(fb ? fb->framebuffer : nullptr, color, depth, rp.clearColor, rp.clearDepth, rp.clearStencil); + renderManager_.BindFramebufferAsRenderTarget(fb ? fb->framebuffer : nullptr, color, depth, stencil, rp.clearColor, rp.clearDepth, rp.clearStencil); } void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) { diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 2dac9803fa..fd223172ca 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -1339,8 +1339,9 @@ void VKContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPass VKFramebuffer *fb = (VKFramebuffer *)fbo; VKRRenderPassAction color = (VKRRenderPassAction)rp.color; VKRRenderPassAction depth = (VKRRenderPassAction)rp.depth; + VKRRenderPassAction stencil = (VKRRenderPassAction)rp.stencil; - renderManager_.BindFramebufferAsRenderTarget(fb ? fb->GetFB() : nullptr, color, depth, rp.clearColor, rp.clearDepth, rp.clearStencil); + renderManager_.BindFramebufferAsRenderTarget(fb ? fb->GetFB() : nullptr, color, depth, stencil, rp.clearColor, rp.clearDepth, rp.clearStencil); curFramebuffer_ = fb; } From 5798c0cc736ff8c4dbdc9ee385513d5bc541174f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 18 Jan 2018 21:38:22 -0800 Subject: [PATCH 052/291] Vulkan: Correct zero stencil upload fast path. --- GPU/Vulkan/StencilBufferVulkan.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/GPU/Vulkan/StencilBufferVulkan.cpp b/GPU/Vulkan/StencilBufferVulkan.cpp index cb873765f1..9a7ce2a728 100644 --- a/GPU/Vulkan/StencilBufferVulkan.cpp +++ b/GPU/Vulkan/StencilBufferVulkan.cpp @@ -116,18 +116,6 @@ bool FramebufferManagerVulkan::NotifyStencilUpload(u32 addr, int size, bool skip VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - if (usedBits == 0) { - if (skipZero) { - // Common when creating buffers, it's already 0. We're done. - return false; - } - - // TODO: Find a nice way to clear alpha here too. - draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }); - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE); - return true; - } - shaderManagerVulkan_->DirtyLastShader(); textureCacheVulkan_->ForgetLastTexture(); @@ -150,6 +138,18 @@ bool FramebufferManagerVulkan::NotifyStencilUpload(u32 addr, int size, bool skip VkDescriptorSet descSet = vulkan2D_->GetDescriptorSet(overrideImageView_, nearestSampler_, VK_NULL_HANDLE, VK_NULL_HANDLE); + if (usedBits == 0) { + // Note: Even with skipZero, we don't necessarily start framebuffers at 0 in Vulkan. Clear anyway. + // Not an actual clear, because we need to draw to alpha only as well. + uint32_t value = 0; + renderManager->PushConstants(vulkan2D_->GetPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4, &value); + renderManager->SetStencilParams(0xFF, 0xFF, 0x00); + renderManager->Draw(vulkan2D_->GetPipelineLayout(), descSet, 0, nullptr, VK_NULL_HANDLE, 0, 3); // full screen triangle + + // Skip the loop. + values = 0; + } + for (int i = 1; i < values; i += i) { if (!(usedBits & i)) { // It's already zero, let's skip it. From e98f265d68943b833b87eebbb5f7ec59876d17c0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 18 Jan 2018 21:45:26 -0800 Subject: [PATCH 053/291] GLES: Prevent writing to gutter in readback. This also read outside the conv buffer. Prevents crash on startup for Brave Story. Now, it just has major graphical issues. --- ext/native/thin3d/GLQueueRunner.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 0434a997f8..92320161ce 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -949,9 +949,10 @@ void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) { void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { // TODO: Maybe move data format conversion here, and always read back 8888. Drivers // don't usually provide very optimized conversion implementations, though some do. + // Just need to be careful about dithering, which may break Danganronpa. int bpp = (int)Draw::DataFormatSizeInBytes(destFormat); for (int y = 0; y < height; y++) { - memcpy(pixels + y * pixelStride * bpp, readbackBuffer_ + y * width * bpp, pixelStride * bpp); + memcpy(pixels + y * pixelStride * bpp, readbackBuffer_ + y * width * bpp, width * bpp); } } From acb692677babb56105e402ebef836c69b0c3079e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 18 Jan 2018 22:17:29 -0800 Subject: [PATCH 054/291] GLES: Accept a color mask for clears. Otherwise, we end up clearing RGB when we try to only clear alpha, which is fairly common. Makes Valkyria Chronicles 3 action mode visible again. --- GPU/GLES/DrawEngineGLES.cpp | 4 +++- GPU/GLES/StencilBufferGLES.cpp | 7 ++----- ext/native/thin3d/GLQueueRunner.cpp | 8 ++++---- ext/native/thin3d/GLQueueRunner.h | 1 + ext/native/thin3d/GLRenderManager.cpp | 1 + ext/native/thin3d/GLRenderManager.h | 3 ++- ext/native/thin3d/thin3d_gl.cpp | 2 +- 7 files changed, 14 insertions(+), 12 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 1aa3a0dd66..d5cf5ae824 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -709,11 +709,13 @@ rotateVBO: } GLbitfield target = 0; + // Without this, we will clear RGB when clearing stencil, which breaks games. + uint8_t rgbaMask = (colorMask ? 7 : 0) | (alphaMask ? 8 : 0); if (colorMask || alphaMask) target |= GL_COLOR_BUFFER_BIT; if (alphaMask) target |= GL_STENCIL_BUFFER_BIT; if (depthMask) target |= GL_DEPTH_BUFFER_BIT; - render_->Clear(clearColor, clearDepth, clearColor >> 24, target); + render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask); framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); int scissorX1 = gstate.getScissorX1(); diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 980c3d4406..0f3a19b881 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -113,10 +113,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe if (dstBuffer->fbo) { draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }); } - // TODO: This incorrectly does not apply to the clear currently. - render_->SetNoBlendAndMask(0x8); - render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - render_->SetNoBlendAndMask(0xF); + render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT, 0x8); gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE); return true; } @@ -172,7 +169,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe textureCacheGL_->ForgetLastTexture(); // We must bind the program after starting the render pass, and set the color mask after clearing. - render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT); + render_->Clear(0, 0, 0, GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 0x8); render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF); render_->BindProgram(stencilUploadProgram_); render_->SetNoBlendAndMask(0x8); diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 92320161ce..1fcd63fdac 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -498,10 +498,10 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { break; case GLRRenderCommand::CLEAR: glDisable(GL_SCISSOR_TEST); - // TODO: We sometimes pass a color mask in that we want to respect (StencilBufferGLES.) - // We want to clear to only clear alpha, in that case. - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - colorMask = 0xF; + if (c.clear.colorMask != colorMask) { + glColorMask(c.clear.colorMask & 1, (c.clear.colorMask >> 1) & 1, (c.clear.colorMask >> 2) & 1, (c.clear.colorMask >> 3) & 1); + colorMask = c.clear.colorMask; + } if (c.clear.clearMask & GL_COLOR_BUFFER_BIT) { float color[4]; Uint8x4ToFloat4(color, c.clear.clearColor); diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index f11e9fec44..22dfbaef84 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -117,6 +117,7 @@ struct GLRRenderData { float clearZ; int clearStencil; int clearMask; // VK_IMAGE_ASPECT_COLOR_BIT etc + int colorMask; // Like blend, but for the clear. } clear; struct { int slot; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 3cbc3a2dd8..7989f0b662 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -193,6 +193,7 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende } if (clearMask) { data.clear.clearMask = clearMask; + data.clear.colorMask = 0xF; step->commands.push_back(data); } diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 711aa143fb..c5d728505e 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -571,13 +571,14 @@ public: curRenderStep_->commands.push_back(data); } - void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask) { + void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask, int colorMask = 0xF) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::CLEAR }; data.clear.clearMask = clearMask; data.clear.clearColor = clearColor; data.clear.clearZ = clearZ; data.clear.clearStencil = clearStencil; + data.clear.colorMask = colorMask; curRenderStep_->commands.push_back(data); } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 82d66dd0e1..a16411fbe7 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -186,7 +186,7 @@ public: bool depthWriteEnabled; GLuint depthComp; // TODO: Two-sided - GLboolean stencilEnabled; + bool stencilEnabled; GLuint stencilFail; GLuint stencilZFail; GLuint stencilPass; From e531a7da437b6ee681fc54d24f692bc166e73d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 19 Jan 2018 20:24:09 +0100 Subject: [PATCH 055/291] gl-render-manager: Implement logic ops --- GPU/GLES/StateMappingGLES.cpp | 10 +--------- ext/native/thin3d/GLQueueRunner.cpp | 24 ++++++++++++++++++++++++ ext/native/thin3d/GLQueueRunner.h | 6 ++++++ ext/native/thin3d/GLRenderManager.h | 10 ++++++++++ 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index 0b9229e365..0b96bb05e4 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -229,15 +229,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) { #ifndef USING_GLES2 if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { - // TODO: Make this dynamic - // Logic Ops - if (gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_COPY) { - // TODO: Fix logic ops. - //glstate.colorLogicOp.enable(); - //glstate.logicOp.set(logicOps[gstate.getLogicOp()]); - } else { - //glstate.colorLogicOp.disable(); - } + renderManager->SetLogicOp(gstate.isLogicOpEnabled(), logicOps[gstate.getLogicOp()]); } #endif } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 1fcd63fdac..bec22244ae 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -405,6 +405,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glDisable(GL_CULL_FACE); glDisable(GL_DITHER); glEnable(GL_SCISSOR_TEST); +#ifndef USING_GLES2 + glDisable(GL_COLOR_LOGIC_OP); +#endif /* #ifndef USING_GLES2 @@ -430,12 +433,14 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { int colorMask = -1; int depthMask = -1; int depthFunc = -1; + int logicOp = -1; GLuint curArrayBuffer = (GLuint)-1; GLuint curElemArrayBuffer = (GLuint)-1; bool depthEnabled = false; bool blendEnabled = false; bool cullEnabled = false; bool ditherEnabled = false; + bool logicEnabled = false; GLuint blendEqColor = (GLuint)-1; GLuint blendEqAlpha = (GLuint)-1; @@ -496,6 +501,22 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { colorMask = c.blend.mask; } break; + case GLRRenderCommand::LOGICOP: +#ifndef USING_GLES2 + if (c.logic.enabled) { + if (!logicEnabled) { + glEnable(GL_COLOR_LOGIC_OP); + logicEnabled = true; + } + if (logicOp != c.logic.logicOp) { + glLogicOp(c.logic.logicOp); + } + } else if (!c.logic.enabled && logicEnabled) { + glDisable(GL_COLOR_LOGIC_OP); + logicEnabled = false; + } +#endif + break; case GLRRenderCommand::CLEAR: glDisable(GL_SCISSOR_TEST); if (c.clear.colorMask != colorMask) { @@ -814,6 +835,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); +#ifndef USING_GLES2 + glDisable(GL_COLOR_LOGIC_OP); +#endif glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 22dfbaef84..a4175405f2 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -32,6 +32,7 @@ enum class GLRRenderCommand : uint8_t { STENCILOP, BLEND, BLENDCOLOR, + LOGICOP, UNIFORM4I, UNIFORM4F, UNIFORMMATRIX, @@ -55,6 +56,7 @@ enum class GLRRenderCommand : uint8_t { // TODO: Bloated since the biggest struct decides the size. Will need something more efficient (separate structs with shared // type field, smashed right after each other?) +// Also, all GLenums are really only 16 bits. struct GLRRenderData { GLRRenderCommand cmd; union { @@ -71,6 +73,10 @@ struct GLRRenderData { struct { float color[4]; } blendColor; + struct { + GLboolean enabled; + GLenum logicOp; + } logic; struct { GLboolean enabled; GLboolean write; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index c5d728505e..345b8ad6f2 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -505,6 +505,16 @@ public: curRenderStep_->commands.push_back(data); } +#ifndef USING_GLES2 + void SetLogicOp(bool enabled, GLenum logicOp) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::LOGICOP }; + data.logic.enabled = enabled; + data.logic.logicOp = logicOp; + curRenderStep_->commands.push_back(data); + } +#endif + void SetStencilFunc(bool enabled, GLenum func, uint8_t refValue, uint8_t compareMask) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::STENCILFUNC }; From b3ed3ea0fbb1d6dd74418ecdd31df311bb6be42f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 19 Jan 2018 21:19:52 -0800 Subject: [PATCH 056/291] GLES: Fix intra-buffer block transfers. Makes Grand Knights History look a bit better. --- ext/native/thin3d/GLQueueRunner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index bec22244ae..381934224b 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -850,7 +850,7 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) { const GLOffset2D &dstPos = step.copy.dstPos; GLRFramebuffer *src = step.copy.src; - GLRFramebuffer *dst = step.copy.src; + GLRFramebuffer *dst = step.copy.dst; int srcLevel = 0; int dstLevel = 0; From b956263a968764d0d3fb4dd2f05c4e2e02b25d56 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 19 Jan 2018 21:25:56 -0800 Subject: [PATCH 057/291] GLES: Consistently reset state on new steps. It'd be nice to avoid this dependency, but since every step forgets the current state, and these functions are called in a lot of places, it's tricky to manage. Fixes graphics in Grand Knights History (framebuf copy creating a new step, resetting blending state.) --- ext/native/thin3d/GLRenderManager.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 7989f0b662..2cb820982d 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -4,6 +4,7 @@ #include "gfx_es2/gpu_features.h" #include "thread/threadutil.h" #include "base/logging.h" +#include "GPU/GPUState.h" #if 0 // def _DEBUG #define VLOG ILOG @@ -198,6 +199,9 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende } curRenderStep_ = step; + + // Every step clears this state. + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE); } void GLRenderManager::BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment) { @@ -210,17 +214,20 @@ void GLRenderManager::BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, } void GLRenderManager::CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLOffset2D dstPos, int aspectMask) { - GLRStep * step = new GLRStep{ GLRStepType::COPY }; + GLRStep *step = new GLRStep{ GLRStepType::COPY }; step->copy.srcRect = srcRect; step->copy.dstPos = dstPos; step->copy.src = src; step->copy.dst = dst; step->copy.aspectMask = aspectMask; steps_.push_back(step); + + // Every step clears this state. + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE); } void GLRenderManager::BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLRect2D dstRect, int aspectMask, bool filter) { - GLRStep * step = new GLRStep{ GLRStepType::BLIT }; + GLRStep *step = new GLRStep{ GLRStepType::BLIT }; step->blit.srcRect = srcRect; step->blit.dstRect = dstRect; step->blit.src = src; @@ -228,6 +235,9 @@ void GLRenderManager::BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLR step->blit.aspectMask = aspectMask; step->blit.filter = filter; steps_.push_back(step); + + // Every step clears this state. + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE); } bool GLRenderManager::CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride) { @@ -238,6 +248,9 @@ bool GLRenderManager::CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspec step->readback.dstFormat = destFormat; steps_.push_back(step); + // Every step clears this state. + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE); + curRenderStep_ = nullptr; FlushSync(); From 7316261eac2b3cad6c9d2ae5e355371265b23420 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 19 Jan 2018 21:32:45 -0800 Subject: [PATCH 058/291] Vulkan: Fix alpha clear on stencil upload. We need to do it always, because otherwise alpha is not cleared. --- GPU/Vulkan/StencilBufferVulkan.cpp | 31 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/GPU/Vulkan/StencilBufferVulkan.cpp b/GPU/Vulkan/StencilBufferVulkan.cpp index 9a7ce2a728..febe32c61c 100644 --- a/GPU/Vulkan/StencilBufferVulkan.cpp +++ b/GPU/Vulkan/StencilBufferVulkan.cpp @@ -38,11 +38,15 @@ layout (location = 0) in vec2 v_texcoord0; layout (location = 0) out vec4 fragColor0; void main() { - vec4 index = texture(tex, v_texcoord0); - int indexBits = int(floor(index.a * 255.99)) & 0xFF; - if ((indexBits & u_stencilValue) == 0) - discard; - fragColor0 = index.aaaa; + if (u_stencilValue == 0) { + fragColor0 = vec4(0.0); + } else { + vec4 index = texture(tex, v_texcoord0); + int indexBits = int(floor(index.a * 255.99)) & 0xFF; + if ((indexBits & u_stencilValue) == 0) + discard; + fragColor0 = index.aaaa; + } } )"; @@ -138,17 +142,12 @@ bool FramebufferManagerVulkan::NotifyStencilUpload(u32 addr, int size, bool skip VkDescriptorSet descSet = vulkan2D_->GetDescriptorSet(overrideImageView_, nearestSampler_, VK_NULL_HANDLE, VK_NULL_HANDLE); - if (usedBits == 0) { - // Note: Even with skipZero, we don't necessarily start framebuffers at 0 in Vulkan. Clear anyway. - // Not an actual clear, because we need to draw to alpha only as well. - uint32_t value = 0; - renderManager->PushConstants(vulkan2D_->GetPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4, &value); - renderManager->SetStencilParams(0xFF, 0xFF, 0x00); - renderManager->Draw(vulkan2D_->GetPipelineLayout(), descSet, 0, nullptr, VK_NULL_HANDLE, 0, 3); // full screen triangle - - // Skip the loop. - values = 0; - } + // Note: Even with skipZero, we don't necessarily start framebuffers at 0 in Vulkan. Clear anyway. + // Not an actual clear, because we need to draw to alpha only as well. + uint32_t value = 0; + renderManager->PushConstants(vulkan2D_->GetPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4, &value); + renderManager->SetStencilParams(0xFF, 0xFF, 0x00); + renderManager->Draw(vulkan2D_->GetPipelineLayout(), descSet, 0, nullptr, VK_NULL_HANDLE, 0, 3); // full screen triangle for (int i = 1; i < values; i += i) { if (!(usedBits & i)) { From bdf7fdc7a34e59b5a22f3b6b5290851e07b56cf3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 19 Jan 2018 21:48:38 -0800 Subject: [PATCH 059/291] GLES: Actually stop the thread on shutdown. Fixes shutdown. --- Windows/GPU/WindowsGLContext.cpp | 2 ++ ext/native/thin3d/GLRenderManager.cpp | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index ac48df35fd..53cf6580f8 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -386,6 +386,8 @@ void WindowsGLContext::SwapInterval(int interval) { } void WindowsGLContext::Shutdown() { + if (renderManager_) + renderManager_->StopThread(); glslang::FinalizeProcess(); } diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 2cb820982d..63c9ecbb8f 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -69,11 +69,16 @@ void GLRenderManager::ThreadStart() { } void GLRenderManager::ThreadEnd() { + // Wait for any shutdown to complete in StopThread(). + std::unique_lock lock(mutex_); queueRunner_.DestroyDeviceObjects(); VLOG("PULL: Quitting"); } bool GLRenderManager::ThreadFrame() { + std::unique_lock lock(mutex_); + if (!run_) + return false; { if (nextFrame) { threadFrame_++; @@ -126,7 +131,8 @@ void GLRenderManager::StopThread() { } } - // TODO: Wait for something here! + // Wait until we've definitely stopped the threadframe. + std::unique_lock lock(mutex_); ILOG("GL submission thread paused. Frame=%d", curFrame_); From db0989a9d0e2d0d298a4e8a8945d4d26b878c650 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 19 Jan 2018 22:41:18 -0800 Subject: [PATCH 060/291] Debugger: Fix texture preview in GLES. Also, fix issues with the first view of a texture in Vulkan / D3D11. --- GPU/D3D11/TextureCacheD3D11.cpp | 14 +++++++------ GPU/GLES/TextureCacheGLES.cpp | 29 +++++++++++++++++++++++---- GPU/Vulkan/TextureCacheVulkan.cpp | 16 ++++++++------- ext/native/thin3d/GLQueueRunner.cpp | 21 +++++++++++++++++++ ext/native/thin3d/GLQueueRunner.h | 2 +- ext/native/thin3d/GLRenderManager.cpp | 16 +++++++++++++++ ext/native/thin3d/GLRenderManager.h | 2 +- 7 files changed, 81 insertions(+), 19 deletions(-) diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 425d8b738b..fc12d417db 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -775,16 +775,18 @@ bool TextureCacheD3D11::DecodeTexture(u8 *output, const GPUgstate &state) { } bool TextureCacheD3D11::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) { - ApplyTexture(); SetTexture(false); if (!nextTexture_) return false; + // Apply texture may need to rebuild the texture if we're about to render, or bind a framebuffer. + TexCacheEntry *entry = nextTexture_; + ApplyTexture(); + // TODO: Centralize. - if (nextTexture_->framebuffer) { - VirtualFramebuffer *vfb = nextTexture_->framebuffer; - bool flipY = GetGPUBackend() == GPUBackend::OPENGL && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE; - buffer.Allocate(vfb->bufferWidth, vfb->bufferHeight, GPU_DBG_FORMAT_8888, flipY); + if (entry->framebuffer) { + VirtualFramebuffer *vfb = entry->framebuffer; + buffer.Allocate(vfb->bufferWidth, vfb->bufferHeight, GPU_DBG_FORMAT_8888, false); bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, 0, 0, vfb->bufferWidth, vfb->bufferHeight, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), vfb->bufferWidth); // Vulkan requires us to re-apply all dynamic state for each command buffer, and the above will cause us to start a new cmdbuf. // So let's dirty the things that are involved in Vulkan dynamic state. Readbacks are not frequent so this won't hurt other backends. @@ -794,7 +796,7 @@ bool TextureCacheD3D11::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level return retval; } - ID3D11Texture2D *texture = (ID3D11Texture2D *)nextTexture_->texturePtr; + ID3D11Texture2D *texture = (ID3D11Texture2D *)entry->texturePtr; if (!texture) return false; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 8560438e04..39b3c7ede1 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -907,19 +907,40 @@ bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) } SetTexture(true); + if (!nextTexture_) + return false; + + // Apply texture may need to rebuild the texture if we're about to render, or bind a framebuffer. + TexCacheEntry *entry = nextTexture_; ApplyTexture(); + + // TODO: Centralize? + if (entry->framebuffer) { + VirtualFramebuffer *vfb = entry->framebuffer; + buffer.Allocate(vfb->bufferWidth, vfb->bufferHeight, GPU_DBG_FORMAT_8888, false); + bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, 0, 0, vfb->bufferWidth, vfb->bufferHeight, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), vfb->bufferWidth); + // Vulkan requires us to re-apply all dynamic state for each command buffer, and the above will cause us to start a new cmdbuf. + // So let's dirty the things that are involved in Vulkan dynamic state. Readbacks are not frequent so this won't hurt other backends. + gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE); + // We may have blitted to a temp FBO. + framebufferManager_->RebindFramebuffer(); + return retval; + } + + GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + + // Not a framebuffer, so let's assume these are right. int w = gstate.getTextureWidth(level); int h = gstate.getTextureHeight(level); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); if (level != 0) { gstate = saved; } buffer.Allocate(w, h, GE_FORMAT_8888, false); - glPixelStorei(GL_PACK_ALIGNMENT, 4); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.GetData()); + renderManager->CopyImageToMemorySync(entry->textureName, level, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, (uint8_t *)buffer.GetData(), w); + gstate_c.Dirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); + framebufferManager_->RebindFramebuffer(); return true; #else diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 4b844b192b..041ed911e8 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -784,16 +784,18 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePt } bool TextureCacheVulkan::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) { - ApplyTexture(); SetTexture(false); if (!nextTexture_) return false; + // Apply texture may need to rebuild the texture if we're about to render, or bind a framebuffer. + TexCacheEntry *entry = nextTexture_; + ApplyTexture(); + // TODO: Centralize? - if (nextTexture_->framebuffer) { - VirtualFramebuffer *vfb = nextTexture_->framebuffer; - bool flipY = GetGPUBackend() == GPUBackend::OPENGL && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE; - buffer.Allocate(vfb->bufferWidth, vfb->bufferHeight, GPU_DBG_FORMAT_8888, flipY); + if (entry->framebuffer) { + VirtualFramebuffer *vfb = entry->framebuffer; + buffer.Allocate(vfb->bufferWidth, vfb->bufferHeight, GPU_DBG_FORMAT_8888, false); bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, 0, 0, vfb->bufferWidth, vfb->bufferHeight, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), vfb->bufferWidth); // Vulkan requires us to re-apply all dynamic state for each command buffer, and the above will cause us to start a new cmdbuf. // So let's dirty the things that are involved in Vulkan dynamic state. Readbacks are not frequent so this won't hurt other backends. @@ -803,9 +805,9 @@ bool TextureCacheVulkan::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int leve return retval; } - if (!nextTexture_->vkTex || !nextTexture_->vkTex->texture_) + if (!entry->vkTex || !entry->vkTex->texture_) return false; - VulkanTexture *texture = nextTexture_->vkTex->texture_; + VulkanTexture *texture = entry->vkTex->texture_; VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); GPUDebugBufferFormat bufferFormat; diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 381934224b..d7a724ae25 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -947,7 +947,28 @@ void GLQueueRunner::PerformReadback(const GLRStep &pass) { } void GLQueueRunner::PerformReadbackImage(const GLRStep &pass) { + GLRTexture *tex = pass.readback_image.texture; + glBindTexture(GL_TEXTURE_2D, tex->texture); + + CHECK_GL_ERROR_IF_DEBUG(); + + int pixelStride = pass.readback_image.srcRect.w; + glPixelStorei(GL_PACK_ALIGNMENT, 4); + + GLRect2D rect = pass.readback.srcRect; + + int size = 4 * rect.w * rect.h; + if (size > readbackBufferSize_) { + delete[] readbackBuffer_; + readbackBuffer_ = new uint8_t[size]; + readbackBufferSize_ = size; + } + + glPixelStorei(GL_PACK_ALIGNMENT, 4); + glGetTexImage(GL_TEXTURE_2D, pass.readback_image.mipLevel, GL_RGBA, GL_UNSIGNED_BYTE, readbackBuffer_); + + CHECK_GL_ERROR_IF_DEBUG(); } void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) { diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index a4175405f2..362d3e30f3 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -301,7 +301,7 @@ struct GLRStep { Draw::DataFormat dstFormat; } readback; struct { - GLint texture; + GLRTexture *texture; GLRect2D srcRect; int mipLevel; } readback_image; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 63c9ecbb8f..33990e3db1 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -276,6 +276,22 @@ bool GLRenderManager::CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspec return true; } +void GLRenderManager::CopyImageToMemorySync(GLRTexture *texture, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride) { + GLRStep *step = new GLRStep{ GLRStepType::READBACK_IMAGE }; + step->readback_image.texture = texture; + step->readback_image.mipLevel = mipLevel; + step->readback_image.srcRect = { x, y, w, h }; + steps_.push_back(step); + + // Every step clears this state. + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE); + + curRenderStep_ = nullptr; + FlushSync(); + + queueRunner_.CopyReadbackBuffer(w, h, Draw::DataFormat::R8G8B8A8_UNORM, destFormat, pixelStride, pixels); +} + void GLRenderManager::BeginFrame() { VLOG("BeginFrame"); diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 345b8ad6f2..b8933ed074 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -313,7 +313,7 @@ public: void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, GLRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil); void BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment); bool CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride); - void CopyImageToMemorySync(GLuint texture, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride); + void CopyImageToMemorySync(GLRTexture *texture, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride); void CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLOffset2D dstPos, int aspectMask); void BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLRect2D dstRect, int aspectMask, bool filter); From 9945e011c6304b0b7e93733b261766640c77d61e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 19 Jan 2018 23:03:08 -0800 Subject: [PATCH 061/291] GLES: Avoid a shutdown race condition. Also handle DeviceLost before shutdown better. --- GPU/GLES/DrawEngineGLES.cpp | 10 +++++++++- Windows/EmuThread.cpp | 5 ++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index d5cf5ae824..68257d3dce 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -172,18 +172,26 @@ void DrawEngineGLES::InitDeviceObjects() { } void DrawEngineGLES::DestroyDeviceObjects() { + // Beware: this could be called twice in a row, sometimes. for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { + if (!frameData_[i].pushVertex && !frameData_[i].pushIndex) + continue; + render_->UnregisterPushBuffer(i, frameData_[i].pushVertex); render_->UnregisterPushBuffer(i, frameData_[i].pushIndex); frameData_[i].pushVertex->Destroy(); frameData_[i].pushIndex->Destroy(); delete frameData_[i].pushVertex; delete frameData_[i].pushIndex; + frameData_[i].pushVertex = nullptr; + frameData_[i].pushIndex = nullptr; } ClearTrackedVertexArrays(); - render_->DeleteInputLayout(softwareInputLayout_); + if (softwareInputLayout_) + render_->DeleteInputLayout(softwareInputLayout_); + softwareInputLayout_ = nullptr; } void DrawEngineGLES::ClearInputLayoutMap() { diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index da187068d6..c48094bf79 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -105,9 +105,8 @@ void RenderThreadFunc() { } g_graphicsContext->ThreadStart(); - while (emuThreadState != THREAD_SHUTDOWN) { - if (!g_graphicsContext->ThreadFrame()) - break; + while (g_graphicsContext->ThreadFrame()) { + continue; } g_graphicsContext->ThreadEnd(); g_graphicsContext->ShutdownFromRenderThread(); From ccdb4d186d9d82dc7979c4aadb6e91edb4560f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 20 Jan 2018 00:05:59 +0100 Subject: [PATCH 062/291] gl-render-manager: Fix HW tesselation. Remove 1D texture support, likely no benefit. --- GPU/Common/DrawEngineCommon.h | 1 + GPU/GLES/DrawEngineGLES.cpp | 132 +++++++------------------ GPU/GLES/DrawEngineGLES.h | 10 +- GPU/GLES/GPU_GLES.cpp | 3 +- GPU/GLES/ShaderManagerGLES.cpp | 12 +-- GPU/GLES/TextureCacheGLES.cpp | 6 -- GPU/GLES/VertexShaderGeneratorGLES.cpp | 19 ++-- UI/GameSettingsScreen.cpp | 15 +-- ext/native/gfx_es2/gpu_features.cpp | 2 + ext/native/gfx_es2/gpu_features.h | 2 + ext/native/thin3d/GLQueueRunner.cpp | 18 ++-- ext/native/thin3d/GLQueueRunner.h | 1 - 12 files changed, 80 insertions(+), 141 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 961e5dad5e..24599a094b 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -170,6 +170,7 @@ protected: colStride = 4; } virtual void SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) = 0; + virtual void EndFrame() {} }; TessellationDataTransfer *tessDataTransfer; }; diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 68257d3dce..77717aea19 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -133,7 +133,7 @@ DrawEngineGLES::DrawEngineGLES(Draw::DrawContext *draw) : vai_(256), draw_(draw) InitDeviceObjects(); - tessDataTransfer = new TessellationDataTransferGLES(gl_extensions.VersionGEThan(3, 0, 0)); + tessDataTransfer = new TessellationDataTransferGLES(render_); } DrawEngineGLES::~DrawEngineGLES() { @@ -211,6 +211,7 @@ void DrawEngineGLES::EndFrame() { FrameData &frameData = frameData_[render_->GetCurFrame()]; frameData.pushIndex->End(); frameData.pushVertex->End(); + tessDataTransfer->EndFrame(); } struct GlTypeInfo { @@ -761,7 +762,6 @@ rotateVBO: #ifndef MOBILE_DEVICE host->GPUNotifyDraw(); #endif - CHECK_GL_ERROR_IF_DEBUG(); } bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const { @@ -769,103 +769,45 @@ bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const { } void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) { - // TODO: Implement with the render manager - /* -#ifndef USING_GLES2 - if (isAllowTexture1D_) { - // Position - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_1D, data_tex[0]); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (prevSize < size) { - glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, size, 0, GL_RGBA, GL_FLOAT, (GLfloat*)pos); - prevSize = size; - } else { - glTexSubImage1D(GL_TEXTURE_1D, 0, 0, size, GL_RGBA, GL_FLOAT, (GLfloat*)pos); - } + // Removed the 1D texture support, it's unlikely to be relevant for performance. + if (data_tex[0]) + renderManager_->DeleteTexture(data_tex[0]); + uint8_t *pos_data = new uint8_t[size * sizeof(float) * 4]; + memcpy(pos_data, pos, size * sizeof(float) * 4); + data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D); + renderManager_->TextureImage(data_tex[0], 0, size, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, pos_data, false); + renderManager_->FinalizeTexture(data_tex[0], 0, false); + renderManager_->BindTexture(4, data_tex[0]); - // Texcoords - if (hasTexCoords) { - glActiveTexture(GL_TEXTURE5); - glBindTexture(GL_TEXTURE_1D, data_tex[1]); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (prevSizeTex < size) { - glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, size, 0, GL_RGBA, GL_FLOAT, (GLfloat*)tex); - prevSizeTex = size; - } else { - glTexSubImage1D(GL_TEXTURE_1D, 0, 0, size, GL_RGBA, GL_FLOAT, (GLfloat*)tex); - } - } + // Texcoords + if (hasTexCoords) { + if (data_tex[1]) + renderManager_->DeleteTexture(data_tex[1]); + uint8_t *tex_data = new uint8_t[size * sizeof(float) * 4]; + memcpy(tex_data, pos, size * sizeof(float) * 4); + data_tex[1] = renderManager_->CreateTexture(GL_TEXTURE_2D); + renderManager_->TextureImage(data_tex[1], 0, size, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, tex_data, false); + renderManager_->FinalizeTexture(data_tex[1], 0, false); + renderManager_->BindTexture(5, data_tex[1]); + } - // Color - glActiveTexture(GL_TEXTURE6); - glBindTexture(GL_TEXTURE_1D, data_tex[2]); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - int sizeColor = hasColor ? size : 1; - if (prevSizeCol < sizeColor) { - glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, sizeColor, 0, GL_RGBA, GL_FLOAT, (GLfloat*)col); - prevSizeCol = sizeColor; - } else { - glTexSubImage1D(GL_TEXTURE_1D, 0, 0, sizeColor, GL_RGBA, GL_FLOAT, (GLfloat*)col); - } - } else -#endif - { - // Position - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, data_tex[0]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (prevSize < size) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, size, 1, 0, GL_RGBA, GL_FLOAT, (GLfloat*)pos); - prevSize = size; - } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, 1, GL_RGBA, GL_FLOAT, (GLfloat*)pos); - } + if (data_tex[2]) + renderManager_->DeleteTexture(data_tex[2]); + data_tex[2] = renderManager_->CreateTexture(GL_TEXTURE_2D); + int sizeColor = hasColor ? size : 1; + uint8_t *col_data = new uint8_t[sizeColor * sizeof(float) * 4]; + memcpy(col_data, col, sizeColor * sizeof(float) * 4); - // Texcoords - if (hasTexCoords) { - glActiveTexture(GL_TEXTURE5); - glBindTexture(GL_TEXTURE_2D, data_tex[1]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (prevSizeTex < size) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, size, 1, 0, GL_RGBA, GL_FLOAT, (GLfloat*)tex); - prevSizeTex = size; - } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, 1, GL_RGBA, GL_FLOAT, (GLfloat*)tex); - } - } + renderManager_->TextureImage(data_tex[2], 0, sizeColor, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, col_data, false); + renderManager_->FinalizeTexture(data_tex[2], 0, false); + renderManager_->BindTexture(6, data_tex[2]); +} - // Color - glActiveTexture(GL_TEXTURE6); - glBindTexture(GL_TEXTURE_2D, data_tex[2]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - int sizeColor = hasColor ? size : 1; - if (prevSizeCol < sizeColor) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, sizeColor, 1, 0, GL_RGBA, GL_FLOAT, (GLfloat*)col); - prevSizeCol = sizeColor; - } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, sizeColor, 1, GL_RGBA, GL_FLOAT, (GLfloat*)col); +void DrawEngineGLES::TessellationDataTransferGLES::EndFrame() { + for (int i = 0; i < 3; i++) { + if (data_tex[i]) { + renderManager_->DeleteTexture(data_tex[i]); + data_tex[i] = nullptr; } } - glActiveTexture(GL_TEXTURE0); - CHECK_GL_ERROR_IF_DEBUG(); - */ } diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index ea75d346e6..7fa9f1e816 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -202,10 +202,14 @@ private: class TessellationDataTransferGLES : public TessellationDataTransfer { private: GLRTexture *data_tex[3]{}; - bool isAllowTexture1D_; + GLRenderManager *renderManager_; public: - TessellationDataTransferGLES(bool isAllowTexture1D) : TessellationDataTransfer(), isAllowTexture1D_(isAllowTexture1D) { } - ~TessellationDataTransferGLES() { } + TessellationDataTransferGLES(GLRenderManager *renderManager) + : renderManager_(renderManager) { } + ~TessellationDataTransferGLES() { + EndFrame(); + } void SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) override; + void EndFrame() override; // Queues textures for deletion. }; }; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 7887292baa..5417a24a87 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -316,8 +316,7 @@ void GPU_GLES::CheckGPUFeatures() { if (instanceRendering) features |= GPU_SUPPORTS_INSTANCE_RENDERING; - int maxVertexTextureImageUnits; - glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextureImageUnits); + int maxVertexTextureImageUnits = gl_extensions.maxVertexTextureUnits; if (maxVertexTextureImageUnits >= 3) // At least 3 for hardware tessellation features |= GPU_SUPPORTS_VERTEX_TEXTURE_FETCH; diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 4c10e61527..a33ce2b80c 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -168,12 +168,12 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, availableUniforms = vs->GetUniformMask() | fs->GetUniformMask(); std::vector initialize; - initialize.push_back({ &u_tex, 0, 0 }); - initialize.push_back({ &u_fbotex, 0, 1 }); - initialize.push_back({ &u_testtex, 0, 2 }); - initialize.push_back({ &u_tess_pos_tex, 4 }); // Texture unit 4 - initialize.push_back({ &u_tess_tex_tex, 5 }); // Texture unit 5 - initialize.push_back({ &u_tess_col_tex, 6 }); // Texture unit 6 + initialize.push_back({ &u_tex, 0, 0 }); + initialize.push_back({ &u_fbotex, 0, 1 }); + initialize.push_back({ &u_testtex, 0, 2 }); + initialize.push_back({ &u_tess_pos_tex, 0, 4 }); // Texture unit 4 + initialize.push_back({ &u_tess_tex_tex, 0, 5 }); // Texture unit 5 + initialize.push_back({ &u_tess_col_tex, 0, 6 }); // Texture unit 6 program = render->CreateProgram(shaders, semantics, queries, initialize, gstate_c.featureFlags & GPU_SUPPORTS_DUALSOURCE_BLEND); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 39b3c7ede1..61e585a8aa 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -115,7 +115,6 @@ static const GLuint MagFiltGL[2] = { // This should not have to be done per texture! OpenGL is silly yo void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { - CHECK_GL_ERROR_IF_DEBUG(); int minFilt; int magFilt; bool sClamp; @@ -157,7 +156,6 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { float aniso = 0.0f; render_->SetTextureSampler(sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); - CHECK_GL_ERROR_IF_DEBUG(); } void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight) { @@ -735,8 +733,6 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r bool useUnpack = false; uint8_t *pixelData; - CHECK_GL_ERROR_IF_DEBUG(); - // TODO: only do this once u32 texByteAlign = 1; @@ -794,8 +790,6 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r } } - CHECK_GL_ERROR_IF_DEBUG(); - GLuint components = dstFmt == GL_UNSIGNED_SHORT_5_6_5 ? GL_RGB : GL_RGBA; GLuint components2 = components; diff --git a/GPU/GLES/VertexShaderGeneratorGLES.cpp b/GPU/GLES/VertexShaderGeneratorGLES.cpp index 1517d58643..f9de2d312b 100644 --- a/GPU/GLES/VertexShaderGeneratorGLES.cpp +++ b/GPU/GLES/VertexShaderGeneratorGLES.cpp @@ -107,7 +107,6 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, const char *attribute = "attribute"; const char * const * boneWeightDecl = boneWeightAttrDecl; const char *texelFetch = NULL; - bool isAllowTexture1D = false; bool highpFog = false; bool highpTexcoord = false; @@ -135,13 +134,11 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, glslES30 = true; WRITE(p, "#version 330\n"); texelFetch = "texelFetch"; - isAllowTexture1D = true; } else if (gl_extensions.VersionGEThan(3, 0, 0)) { WRITE(p, "#version 130\n"); if (gl_extensions.EXT_gpu_shader4) { WRITE(p, "#extension GL_EXT_gpu_shader4 : enable\n"); texelFetch = "texelFetch"; - isAllowTexture1D = true; } } else { WRITE(p, "#version 110\n"); @@ -374,10 +371,9 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, if (doBezier || doSpline) { *uniformMask |= DIRTY_BEZIERSPLINE; - const char *sampler = !isAllowTexture1D ? "sampler2D" : "sampler1D"; - WRITE(p, "uniform %s u_tess_pos_tex;\n", sampler); - WRITE(p, "uniform %s u_tess_tex_tex;\n", sampler); - WRITE(p, "uniform %s u_tess_col_tex;\n", sampler); + WRITE(p, "uniform sampler2D u_tess_pos_tex;\n"); + WRITE(p, "uniform sampler2D u_tess_tex_tex;\n"); + WRITE(p, "uniform sampler2D u_tess_col_tex;\n"); WRITE(p, "uniform int u_spline_count_u;\n"); @@ -502,12 +498,11 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, WRITE(p, " for (int i = 0; i < 4; i++) {\n"); WRITE(p, " for (int j = 0; j < 4; j++) {\n"); WRITE(p, " int index = (i + v%s) * u_spline_count_u + (j + u%s);\n", doBezier ? " * 3" : "", doBezier ? " * 3" : ""); - const char *index = !isAllowTexture1D ? "ivec2(index, 0)" : "index"; - WRITE(p, " _pos[i * 4 + j] = %s(u_tess_pos_tex, %s, 0).xyz;\n", texelFetch, index); + WRITE(p, " _pos[i * 4 + j] = %s(u_tess_pos_tex, ivec2(index, 0), 0).xyz;\n", texelFetch); if (doTexture && hasTexcoord && hasTexcoordTess) - WRITE(p, " _tex[i * 4 + j] = %s(u_tess_tex_tex, %s, 0).xy;\n", texelFetch, index); + WRITE(p, " _tex[i * 4 + j] = %s(u_tess_tex_tex, ivec2(index, 0), 0).xy;\n", texelFetch); if (hasColor && hasColorTess) - WRITE(p, " _col[i * 4 + j] = %s(u_tess_col_tex, %s, 0).rgba;\n", texelFetch, index); + WRITE(p, " _col[i * 4 + j] = %s(u_tess_col_tex, ivec2(index, 0), 0).rgba;\n", texelFetch); WRITE(p, " }\n"); WRITE(p, " }\n"); WRITE(p, " vec2 tess_pos = position.xy;\n"); @@ -536,7 +531,7 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, if (hasColorTess) WRITE(p, " vec4 col = tess_sample(_col, weights);\n"); else - WRITE(p, " vec4 col = %s(u_tess_col_tex, %s, 0).rgba;\n", texelFetch, !isAllowTexture1D ? "ivec2(0, 0)" : "0"); + WRITE(p, " vec4 col = %s(u_tess_col_tex, ivec2(0, 0), 0).rgba;\n", texelFetch); } if (hasNormal) { // Curved surface is probably always need to compute normal(not sampling from control points) diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 34fec613b6..6b63263d7d 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -63,10 +63,6 @@ #include "Windows/W32Util/ShellUtil.h" #endif -#if !PPSSPP_PLATFORM(UWP) -#include "gfx/gl_common.h" -#endif - extern bool VulkanMayBeAvailable(); GameSettingsScreen::GameSettingsScreen(std::string gamePath, std::string gameID, bool editThenRestore) @@ -85,8 +81,7 @@ bool CheckSupportInstancedTessellationGLES() { return true; #else // TODO: Make work with non-GL backends - int maxVertexTextureImageUnits; - glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextureImageUnits); + int maxVertexTextureImageUnits = gl_extensions.maxVertexTextureUnits; bool vertexTexture = maxVertexTextureImageUnits >= 3; // At least 3 for hardware tessellation bool canUseInstanceID = gl_extensions.EXT_draw_instanced || gl_extensions.ARB_draw_instanced; @@ -100,7 +95,7 @@ bool CheckSupportInstancedTessellationGLES() { #endif } -bool IsBackendSupportHWTess() { +bool DoesBackendSupportHWTess() { switch (GetGPUBackend()) { case GPUBackend::OPENGL: return CheckSupportInstancedTessellationGLES(); @@ -353,7 +348,7 @@ void GameSettingsScreen::CreateViews() { settingInfo_->Show(gr->T("HardwareTessellation Tip", "Uses hardware to make curves, always uses a fixed quality"), e.v); return UI::EVENT_CONTINUE; }); - tessHWEnable_ = IsBackendSupportHWTess() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform; + tessHWEnable_ = DoesBackendSupportHWTess() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform; tessellationHW->SetEnabledPtr(&tessHWEnable_); // In case we're going to add few other antialiasing option like MSAA in the future. @@ -798,13 +793,13 @@ UI::EventReturn GameSettingsScreen::OnSoftwareRendering(UI::EventParams &e) { postProcEnable_ = !g_Config.bSoftwareRendering && (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE); resolutionEnable_ = !g_Config.bSoftwareRendering && (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE); bloomHackEnable_ = !g_Config.bSoftwareRendering && (g_Config.iInternalResolution != 1); - tessHWEnable_ = IsBackendSupportHWTess() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform; + tessHWEnable_ = DoesBackendSupportHWTess() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform; return UI::EVENT_DONE; } UI::EventReturn GameSettingsScreen::OnHardwareTransform(UI::EventParams &e) { vtxCacheEnable_ = !g_Config.bSoftwareRendering && g_Config.bHardwareTransform; - tessHWEnable_ = IsBackendSupportHWTess() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform; + tessHWEnable_ = DoesBackendSupportHWTess() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform; return UI::EVENT_DONE; } diff --git a/ext/native/gfx_es2/gpu_features.cpp b/ext/native/gfx_es2/gpu_features.cpp index c758645fc9..69ffa7c897 100644 --- a/ext/native/gfx_es2/gpu_features.cpp +++ b/ext/native/gfx_es2/gpu_features.cpp @@ -393,6 +393,8 @@ void CheckGLExtensions() { } #endif + glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &gl_extensions.maxVertexTextureUnits); + // This is probably a waste of time, implementations lie. if (gl_extensions.IsGLES || strstr(extString, "GL_ARB_ES2_compatibility") || gl_extensions.VersionGEThan(4, 1)) { const GLint precisions[6] = { diff --git a/ext/native/gfx_es2/gpu_features.h b/ext/native/gfx_es2/gpu_features.h index 2f405546b8..b12b406eee 100644 --- a/ext/native/gfx_es2/gpu_features.h +++ b/ext/native/gfx_es2/gpu_features.h @@ -96,6 +96,8 @@ struct GLExtensions { int range[2][6][2]; // [vs,fs][lowf,mediumf,highf,lowi,mediumi,highi][min,max] int precision[2][6]; // [vs,fs][lowf...] + int maxVertexTextureUnits; + // greater-or-equal than bool VersionGEThan(int major, int minor, int sub = 0); }; diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index d7a724ae25..c07085bf70 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -182,8 +182,6 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { InitCreateFramebuffer(step); break; } - case GLRInitStepType::TEXTURE_SUBDATA: - break; case GLRInitStepType::TEXTURE_IMAGE: { GLRTexture *tex = step.texture_image.texture; @@ -193,13 +191,20 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { glBindTexture(tex->target, tex->texture); boundTexture = tex->texture; } + if (!step.texture_image.data) + Crash(); + // For things to show in RenderDoc, need to split into glTexImage2D(..., nullptr) and glTexSubImage. glTexImage2D(tex->target, step.texture_image.level, step.texture_image.internalFormat, step.texture_image.width, step.texture_image.height, 0, step.texture_image.format, step.texture_image.type, step.texture_image.data); delete[] step.texture_image.data; CHECK_GL_ERROR_IF_DEBUG(); - glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST); - glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST); + tex->wrapS = GL_CLAMP_TO_EDGE; + tex->wrapT = GL_CLAMP_TO_EDGE; + tex->magFilter = step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST; + tex->minFilter = step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST; + glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, tex->wrapS); + glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, tex->wrapT); + glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, tex->magFilter); + glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, tex->minFilter); break; } case GLRInitStepType::TEXTURE_FINALIZE: @@ -210,6 +215,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { boundTexture = tex->texture; } glTexParameteri(tex->target, GL_TEXTURE_MAX_LEVEL, step.texture_finalize.maxLevel); + tex->maxLod = step.texture_finalize.maxLevel; if (step.texture_finalize.genMips) { glGenerateMipmap(tex->target); } diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 362d3e30f3..95d71292f8 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -185,7 +185,6 @@ enum class GLRInitStepType : uint8_t { CREATE_FRAMEBUFFER, TEXTURE_IMAGE, - TEXTURE_SUBDATA, TEXTURE_FINALIZE, BUFFER_SUBDATA, }; From 903bd07d6ed12e7db8b37f0c058eb22ba3beadaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 20 Jan 2018 13:45:32 +0100 Subject: [PATCH 063/291] gl-render-manager: Fix updating sampler modes when texturing from framebuffer --- ext/native/thin3d/GLQueueRunner.cpp | 62 ++++++++++++++++------------- ext/native/thin3d/GLRenderManager.h | 47 ++++++++++------------ 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index c07085bf70..92075a6af9 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -185,7 +185,6 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { case GLRInitStepType::TEXTURE_IMAGE: { GLRTexture *tex = step.texture_image.texture; - _assert_msg_(G3D, tex->canary == GLRTexture::CanaryValue, "Canary has bad value %08x in texture %p", tex->canary, tex); CHECK_GL_ERROR_IF_DEBUG(); if (boundTexture != tex->texture) { glBindTexture(tex->target, tex->texture); @@ -243,21 +242,22 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) { // Color texture is same everywhere glGenFramebuffers(1, &fbo->handle); - glGenTextures(1, &fbo->color_texture); + glGenTextures(1, &fbo->color_texture.texture); + fbo->color_texture.target = GL_TEXTURE_2D; + fbo->color_texture.maxLod = 0.0f; // Create the surfaces. - glBindTexture(GL_TEXTURE_2D, fbo->color_texture); - 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_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - + glBindTexture(GL_TEXTURE_2D, fbo->color_texture.texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - 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_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + fbo->color_texture.wrapS = GL_CLAMP_TO_EDGE; + fbo->color_texture.wrapT = GL_CLAMP_TO_EDGE; + fbo->color_texture.magFilter = GL_LINEAR; + fbo->color_texture.minFilter = GL_LINEAR; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, fbo->color_texture.wrapS); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, fbo->color_texture.wrapT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, fbo->color_texture.magFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, fbo->color_texture.minFilter); if (gl_extensions.IsGLES) { if (gl_extensions.OES_packed_depth_stencil) { @@ -272,7 +272,7 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) { // Bind it all together glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); } else { @@ -292,7 +292,7 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) { // Bind it all together glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer); } @@ -306,7 +306,7 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) { // Bind it all together glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); } @@ -654,7 +654,6 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } if (c.texture.texture) { if (curTex[slot] != c.texture.texture) { - _assert_msg_(G3D, c.texture.texture->canary == GLRTexture::CanaryValue, "Canary has bad value %08x in texture %p", c.texture.texture->canary, c.texture.texture); glBindTexture(c.texture.texture->target, c.texture.texture->texture); curTex[slot] = c.texture.texture; } @@ -672,9 +671,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { activeSlot = slot; } if (c.bind_fb_texture.aspect == GL_COLOR_BUFFER_BIT) { - glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->color_texture); + if (curTex[slot] != &c.bind_fb_texture.framebuffer->color_texture) + glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->color_texture.texture); + curTex[slot] = &c.bind_fb_texture.framebuffer->color_texture; } else { // TODO: Depth texturing? + curTex[slot] = nullptr; } break; } @@ -866,8 +868,8 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) { switch (step.copy.aspectMask) { case GL_COLOR_BUFFER_BIT: - srcTex = src->color_texture; - dstTex = dst->color_texture; + srcTex = src->color_texture.texture; + dstTex = dst->color_texture.texture; break; case GL_DEPTH_BUFFER_BIT: // TODO: Support depth copies. @@ -1026,16 +1028,22 @@ void GLQueueRunner::fbo_ext_create(const GLRInitStep &step) { // Color texture is same everywhere glGenFramebuffersEXT(1, &fbo->handle); - glGenTextures(1, &fbo->color_texture); + glGenTextures(1, &fbo->color_texture.texture); // Create the surfaces. - glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + glBindTexture(GL_TEXTURE_2D, fbo->color_texture.texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - 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_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + fbo->color_texture.target = GL_TEXTURE_2D; + fbo->color_texture.wrapS = GL_CLAMP_TO_EDGE; + fbo->color_texture.wrapT = GL_CLAMP_TO_EDGE; + fbo->color_texture.magFilter = step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST; + fbo->color_texture.minFilter = step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST; + fbo->color_texture.maxLod = 0.0f; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, fbo->color_texture.wrapS); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, fbo->color_texture.wrapT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, fbo->color_texture.magFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, fbo->color_texture.minFilter); fbo->stencil_buffer = 0; fbo->z_buffer = 0; @@ -1047,7 +1055,7 @@ void GLQueueRunner::fbo_ext_create(const GLRInitStep &step) { // Bind it all together glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->color_texture.texture, 0); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); @@ -1166,6 +1174,4 @@ GLRFramebuffer::~GLRFramebuffer() { glDeleteRenderbuffers(1, &stencil_buffer); #endif } - - glDeleteTextures(1, &color_texture); } diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index b8933ed074..7fc308cf91 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -18,6 +18,26 @@ class GLRInputLayout; class GLPushBuffer; +class GLRTexture { +public: + ~GLRTexture() { + if (texture) { + glDeleteTextures(1, &texture); + } + } + GLuint texture = 0; + // Could also trust OpenGL defaults I guess.. + GLenum target = 0xFFFF; + GLenum wrapS = 0xFFFF; + GLenum wrapT = 0xFFFF; + GLenum magFilter = 0xFFFF; + GLenum minFilter = 0xFFFF; + float anisotropy = -100000.0f; + float minLod = -100000.0f; + float maxLod = 100000.0f; + float lodBias = 0.0f; +}; + class GLRFramebuffer { public: GLRFramebuffer(int _width, int _height, bool z_stencil) @@ -29,7 +49,7 @@ public: int numShadows = 1; // TODO: Support this. GLuint handle = 0; - GLuint color_texture = 0; + GLRTexture color_texture; GLuint z_stencil_buffer = 0; // Either this is set, or the two below. GLuint z_buffer = 0; GLuint stencil_buffer = 0; @@ -105,31 +125,6 @@ public: std::unordered_map uniformCache_; }; -class GLRTexture { -public: - ~GLRTexture() { - if (texture) { - glDeleteTextures(1, &texture); - } - canary = 0xd31373d; // deleted - } - enum { - CanaryValue = 0x12345678, - }; - uint32_t canary = CanaryValue; - GLuint texture = 0; - // Could also trust OpenGL defaults I guess.. - GLenum target = 0xFFFF; - GLenum wrapS = 0xFFFF; - GLenum wrapT = 0xFFFF; - GLenum magFilter = 0xFFFF; - GLenum minFilter = 0xFFFF; - float anisotropy = -100000.0f; - float minLod = -100000.0f; - float maxLod = 100000.0f; - float lodBias = 0.0f; -}; - class GLRBuffer { public: GLRBuffer(GLuint target, size_t size) : target_(target), size_((int)size) {} From e5b8d91c9f0c4f5abb6e02fe3cb014a4bc4f4307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 20 Jan 2018 13:55:51 +0100 Subject: [PATCH 064/291] ES2 buildfix - glGetTexImage is not available --- ext/native/thin3d/GLQueueRunner.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 92075a6af9..b7a107bc69 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -961,6 +961,7 @@ void GLQueueRunner::PerformReadbackImage(const GLRStep &pass) { CHECK_GL_ERROR_IF_DEBUG(); +#ifndef USING_GLES2 int pixelStride = pass.readback_image.srcRect.w; glPixelStorei(GL_PACK_ALIGNMENT, 4); @@ -975,6 +976,7 @@ void GLQueueRunner::PerformReadbackImage(const GLRStep &pass) { glPixelStorei(GL_PACK_ALIGNMENT, 4); glGetTexImage(GL_TEXTURE_2D, pass.readback_image.mipLevel, GL_RGBA, GL_UNSIGNED_BYTE, readbackBuffer_); +#endif CHECK_GL_ERROR_IF_DEBUG(); } From 4c927c142185aed7ebd55cf6c484bbe89e473c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 20 Jan 2018 16:57:06 +0100 Subject: [PATCH 065/291] Reintroduce check for GE_LOGIC_COPY --- GPU/GLES/StateMappingGLES.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index 0b96bb05e4..65ea0efdc0 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -229,7 +229,8 @@ void DrawEngineGLES::ApplyDrawState(int prim) { #ifndef USING_GLES2 if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { - renderManager->SetLogicOp(gstate.isLogicOpEnabled(), logicOps[gstate.getLogicOp()]); + renderManager->SetLogicOp(gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_COPY, + logicOps[gstate.getLogicOp()]); } #endif } From f6260c75c926bca294f8d13a737cac4d46ea510d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 07:57:38 -0800 Subject: [PATCH 066/291] GLES: Reset blend state on clear. Because now that resets blending parameters. --- GPU/Common/FramebufferCommon.cpp | 12 ++++++++++++ GPU/GLES/FramebufferManagerGLES.cpp | 2 ++ 2 files changed, 14 insertions(+) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 718500058b..3f93329d22 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -609,6 +609,8 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe // performance-crushing framebuffer reloads from RAM, but we'll have to live with that. if (vfb->last_frame_render != gpuStats.numFlips) { draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); + // GLES resets the blend state on clears. + gstate_c.Dirty(DIRTY_BLEND_STATE); } else { draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } @@ -852,6 +854,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { if (useBufferedRendering_) { draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); } + gstate_c.Dirty(DIRTY_BLEND_STATE); return; } @@ -921,6 +924,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { SetViewport2D(0, 0, pixelWidth_, pixelHeight_); draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_); DrawFramebufferToOutput(Memory::GetPointer(displayFramebufPtr_), displayFormat_, displayStride_, true); + gstate_c.Dirty(DIRTY_BLEND_STATE); return; } } else { @@ -930,6 +934,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { // Bind and clear the backbuffer. This should be the first time during the frame that it's bound. draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); } + gstate_c.Dirty(DIRTY_BLEND_STATE); return; } } @@ -1064,6 +1069,9 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { else if (useBufferedRendering_) { WARN_LOG(FRAMEBUF, "Current VFB lacks an FBO: %08x", vfb->fb_address); } + + // This may get called mid-draw if the game uses an immediate flip. + gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE); } void FramebufferManagerCommon::DecimateFBOs() { @@ -1185,6 +1193,8 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, INFO_LOG(FRAMEBUF, "Resizing FBO for %08x : %d x %d x %d", vfb->fb_address, w, h, vfb->format); if (vfb->fbo) { draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); + // GLES resets the blend state on clears. + gstate_c.Dirty(DIRTY_BLEND_STATE); if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) { BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min((u16)oldWidth, std::min(vfb->bufferWidth, vfb->width)), std::min((u16)oldHeight, std::min(vfb->height, vfb->bufferHeight)), 0); } @@ -1195,6 +1205,8 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, } } else { draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); + // GLES resets the blend state on clears. + gstate_c.Dirty(DIRTY_BLEND_STATE); } if (!vfb->fbo) { diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 711c97b398..adf573502f 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -463,6 +463,7 @@ void FramebufferManagerGLES::ReformatFramebufferFrom(VirtualFramebuffer *vfb, GE if (old == GE_FORMAT_565) { draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); + gstate_c.Dirty(DIRTY_BLEND_STATE); } else { draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } @@ -557,6 +558,7 @@ void FramebufferManagerGLES::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) draw_->BindFramebufferAsRenderTarget(nvfb->fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); } else if (gl_extensions.IsGLES) { draw_->BindFramebufferAsRenderTarget(nvfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); + gstate_c.Dirty(DIRTY_BLEND_STATE); } } From 638cbf725b6bf7ebe52f88ca7ccd344055bd5081 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 07:58:04 -0800 Subject: [PATCH 067/291] GLES: Skip blend reset after stencil upload. We dirty the flag anyway. Avoid extra calls. --- GPU/GLES/StencilBufferGLES.cpp | 1 - ext/native/thin3d/GLQueueRunner.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 0f3a19b881..e86aad078f 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -196,7 +196,6 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe draw_->BlitFramebuffer(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, Draw::FB_STENCIL_BIT, Draw::FB_BLIT_NEAREST); } - render_->SetNoBlendAndMask(0xF); gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); RebindFramebuffer(); return true; diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index b7a107bc69..da262e425d 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -214,7 +214,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { boundTexture = tex->texture; } glTexParameteri(tex->target, GL_TEXTURE_MAX_LEVEL, step.texture_finalize.maxLevel); - tex->maxLod = step.texture_finalize.maxLevel; + tex->maxLod = (float)step.texture_finalize.maxLevel; if (step.texture_finalize.genMips) { glGenerateMipmap(tex->target); } From b566b6cca2c5109bdf3da5da82718d674e249f02 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 08:28:26 -0800 Subject: [PATCH 068/291] D3D11: Remove potentially misleading rebind func. This doesn't override the GPUCommon one, it just shares the same name, which might lead to confusion later. Better not to use the parent. --- GPU/D3D11/FramebufferManagerD3D11.cpp | 9 --------- GPU/D3D11/FramebufferManagerD3D11.h | 1 - 2 files changed, 10 deletions(-) diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 6da4b477c1..c45ec45cd5 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -459,15 +459,6 @@ void FramebufferManagerD3D11::BindPostShader(const PostShaderUniforms &uniforms) context_->PSSetConstantBuffers(0, 1, &postConstants_); } -void FramebufferManagerD3D11::RebindFramebuffer() { - if (currentRenderVfb_ && currentRenderVfb_->fbo) { - draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }); - } else { - // Should this even happen? - draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }); - } -} - void FramebufferManagerD3D11::ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) { if (!useBufferedRendering_ || !vfb->fbo) { return; diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index 1bc40e960e..d951d60e7f 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -58,7 +58,6 @@ public: void BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags); virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; - void RebindFramebuffer(); // TODO: Remove ID3D11Buffer *GetDynamicQuadBuffer() { From 48a07474f8d938cb0070d9979afb9b2c1529f0fb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 08:35:24 -0800 Subject: [PATCH 069/291] GLES: Avoid using failed depal shaders if possible. Better to have one totally broken frame than all totally broken frames. --- GPU/GLES/DepalettizeShaderGLES.cpp | 6 +++++- GPU/GLES/ShaderManagerGLES.cpp | 1 - ext/native/thin3d/GLQueueRunner.cpp | 1 + ext/native/thin3d/GLRenderManager.h | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/GPU/GLES/DepalettizeShaderGLES.cpp b/GPU/GLES/DepalettizeShaderGLES.cpp index bc3a84297f..49e1b36f3c 100644 --- a/GPU/GLES/DepalettizeShaderGLES.cpp +++ b/GPU/GLES/DepalettizeShaderGLES.cpp @@ -139,10 +139,14 @@ DepalShader *DepalShaderCacheGLES::GetDepalettizeShader(uint32_t clutMode, GEBuf auto shader = cache_.find(id); if (shader != cache_.end()) { + DepalShader *depal = shader->second; + // If compile failed previously, try to recover. + if (depal->fragShader->failed || vertexShader_->failed) + return nullptr; return shader->second; } - if (vertexShader_ == 0) { + if (!vertexShader_) { if (!CreateVertexShader()) { // The vertex shader failed, no need to bother trying the fragment. return nullptr; diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index a33ce2b80c..195f8516a1 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -179,7 +179,6 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, // The rest, use the "dirty" mechanism. dirtyUniforms = DIRTY_ALL_UNIFORMS; - CHECK_GL_ERROR_IF_DEBUG(); } LinkedShader::~LinkedShader() { diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index da262e425d..ec874cf119 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -164,6 +164,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { OutputDebugStringUTF8(infoLog); #endif step.create_shader.shader->valid = false; + step.create_shader.shader->failed = true; } delete[] step.create_shader.code; delete[] step.create_shader.desc; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 7fc308cf91..b98dfa1dbb 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -73,6 +73,8 @@ public: } GLuint shader = 0; bool valid = false; + // Warning: Won't know until a future frame. + bool failed = false; }; class GLRProgram { From 3380ab8705de88bc6ae2646082a623f17ca5e7fa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 08:46:34 -0800 Subject: [PATCH 070/291] GLES: Keep the GLRShader desc around. This way we can also log it on link errors. It's not much data. --- GPU/GLES/ShaderManagerGLES.cpp | 11 +++++------ GPU/GLES/ShaderManagerGLES.h | 2 +- ext/native/thin3d/GLQueueRunner.cpp | 5 ++--- ext/native/thin3d/GLQueueRunner.h | 3 +-- ext/native/thin3d/GLRenderManager.h | 8 +++----- 5 files changed, 12 insertions(+), 17 deletions(-) diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 195f8516a1..bb06521ea6 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -44,12 +44,11 @@ #include "GPU/GLES/DrawEngineGLES.h" #include "FramebufferManagerGLES.h" -Shader::Shader(GLRenderManager *render, const char *code, const char *desc, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask) +Shader::Shader(GLRenderManager *render, const char *code, const std::string &desc, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask) : render_(render), failed_(false), useHWTransform_(useHWTransform), attrMask_(attrMask), uniformMask_(uniformMask) { PROFILE_THIS_SCOPE("shadercomp"); isFragment_ = glShaderType == GL_FRAGMENT_SHADER; source_ = code; - std::string descstr(desc); #ifdef SHADERLOG #ifdef _WIN32 OutputDebugStringUTF8(code); @@ -57,7 +56,7 @@ Shader::Shader(GLRenderManager *render, const char *code, const char *desc, uint printf("%s\n", code); #endif #endif - shader = render->CreateShader(glShaderType, source_, descstr); + shader = render->CreateShader(glShaderType, source_, desc); } Shader::~Shader() { @@ -609,7 +608,7 @@ Shader *ShaderManagerGLES::CompileFragmentShader(FShaderID FSID) { return nullptr; } std::string desc = FragmentShaderDesc(FSID); - return new Shader(render_, codeBuffer_, desc.c_str(), GL_FRAGMENT_SHADER, false, 0, uniformMask); + return new Shader(render_, codeBuffer_, desc, GL_FRAGMENT_SHADER, false, 0, uniformMask); } Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { @@ -618,7 +617,7 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { uint64_t uniformMask; GenerateVertexShader(VSID, codeBuffer_, &attrMask, &uniformMask); std::string desc = VertexShaderDesc(VSID); - return new Shader(render_, codeBuffer_, desc.c_str(), GL_VERTEX_SHADER, useHWTransform, attrMask, uniformMask); + return new Shader(render_, codeBuffer_, desc, GL_VERTEX_SHADER, useHWTransform, attrMask, uniformMask); } Shader *ShaderManagerGLES::ApplyVertexShader(int prim, u32 vertType, VShaderID *VSID) { @@ -668,7 +667,7 @@ Shader *ShaderManagerGLES::ApplyVertexShader(int prim, u32 vertType, VShaderID * uint32_t attrMask; uint64_t uniformMask; GenerateVertexShader(vsidTemp, codeBuffer_, &attrMask, &uniformMask); - vs = new Shader(render_, codeBuffer_, VertexShaderDesc(vsidTemp).c_str(), GL_VERTEX_SHADER, false, attrMask, uniformMask); + vs = new Shader(render_, codeBuffer_, VertexShaderDesc(vsidTemp), GL_VERTEX_SHADER, false, attrMask, uniformMask); } vsCache_.Insert(*VSID, vs); diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index b7ee34216b..77b94f9cd2 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -125,7 +125,7 @@ public: class Shader { public: - Shader(GLRenderManager *render, const char *code, const char *desc, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask); + Shader(GLRenderManager *render, const char *code, const std::string &desc, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask); ~Shader(); GLRShader *shader; diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index ec874cf119..536847fc39 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -156,10 +156,10 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { ELOG("Error in shader compilation! %s\n", infoLog); ELOG("Shader source:\n%s\n", (const char *)code); #endif - ERROR_LOG(G3D, "Error in shader compilation for: %s", step.create_shader.desc); + ERROR_LOG(G3D, "Error in shader compilation for: %s", step.create_shader.shader->desc.c_str()); ERROR_LOG(G3D, "Info log: %s", infoLog); ERROR_LOG(G3D, "Shader source:\n%s\n", (const char *)code); - Reporting::ReportMessage("Error in shader compilation: info: %s\n%s\n%s", infoLog, step.create_shader.desc, (const char *)code); + Reporting::ReportMessage("Error in shader compilation: info: %s\n%s\n%s", infoLog, step.create_shader.shader->desc.c_str(), (const char *)code); #ifdef SHADERLOG OutputDebugStringUTF8(infoLog); #endif @@ -167,7 +167,6 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { step.create_shader.shader->failed = true; } delete[] step.create_shader.code; - delete[] step.create_shader.desc; step.create_shader.shader->valid = true; break; } diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 95d71292f8..498177c178 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -199,9 +199,8 @@ struct GLRInitStep { } create_texture; struct { GLRShader *shader; - // These char arrays need to be allocated with new[]. + // This char arrays needs to be allocated with new[]. char *code; - char *desc; // For error logging. GLuint stage; } create_shader; struct { diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index b98dfa1dbb..bbc40210be 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -75,6 +75,7 @@ public: bool valid = false; // Warning: Won't know until a future frame. bool failed = false; + std::string desc; }; class GLRProgram { @@ -227,16 +228,13 @@ public: return step.create_buffer.buffer; } - GLRShader *CreateShader(GLuint stage, std::string code, std::string desc) { + GLRShader *CreateShader(GLuint stage, const std::string &code, const std::string &desc) { GLRInitStep step{ GLRInitStepType::CREATE_SHADER }; step.create_shader.shader = new GLRShader(); + step.create_shader.shader->desc = desc; step.create_shader.stage = stage; step.create_shader.code = new char[code.size() + 1]; memcpy(step.create_shader.code, code.data(), code.size() + 1); - if (!desc.empty()) { - step.create_shader.desc = desc.size() ? new char[desc.size() + 1] : nullptr; - memcpy(step.create_shader.desc, desc.data(), desc.size() + 1); - } initSteps_.push_back(step); return step.create_shader.shader; } From e56ae322fd626ef6118542d28e816c8201ca7dd0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 08:58:09 -0800 Subject: [PATCH 071/291] GLES: Report errors for link failures. Let's not lose reporting on this, it's often an issue... --- ext/native/thin3d/GLQueueRunner.cpp | 23 ++++++++++++++++++++--- ext/native/thin3d/GLRenderManager.h | 1 + 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 536847fc39..863398d745 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -101,12 +101,27 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { GLint bufLength = 0; glGetProgramiv(program->program, GL_INFO_LOG_LENGTH, &bufLength); if (bufLength) { - char* buf = new char[bufLength]; - glGetProgramInfoLog(program->program, bufLength, NULL, buf); + char *buf = new char[bufLength]; + glGetProgramInfoLog(program->program, bufLength, nullptr, buf); + + // TODO: Could be other than vs/fs. Also, we're assuming order here... + const char *vsDesc = step.create_program.shaders[0]->desc.c_str(); + const char *fsDesc = step.create_program.num_shaders > 1 ? step.create_program.shaders[1]->desc.c_str() : nullptr; + const char *vsCode = step.create_program.shaders[0]->code.c_str(); + const char *fsCode = step.create_program.num_shaders > 1 ? step.create_program.shaders[1]->code.c_str() : nullptr; + Reporting::ReportMessage("Error in shader program link: info: %s\nfs: %s\n%s\nvs: %s\n%s", buf, fsDesc, fsCode, vsDesc, vsCode); + ELOG("Could not link program:\n %s", buf); - // We've thrown out the source at this point. Might want to do something about that. + ERROR_LOG(G3D, "VS desc:\n%s", vsDesc); + ERROR_LOG(G3D, "FS desc:\n%s", fsDesc); + ERROR_LOG(G3D, "VS:\n%s\n", vsCode); + ERROR_LOG(G3D, "FS:\n%s\n", fsCode); + #ifdef _WIN32 OutputDebugStringUTF8(buf); + OutputDebugStringUTF8(vsCode); + if (fsCode) + OutputDebugStringUTF8(fsCode); #endif delete[] buf; } else { @@ -166,6 +181,8 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { step.create_shader.shader->valid = false; step.create_shader.shader->failed = true; } + // Before we throw away the code, attach it to the shader for debugging. + step.create_shader.shader->code = code; delete[] step.create_shader.code; step.create_shader.shader->valid = true; break; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index bbc40210be..90502cbb24 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -76,6 +76,7 @@ public: // Warning: Won't know until a future frame. bool failed = false; std::string desc; + std::string code; }; class GLRProgram { From 38161f3c69de5830943c2307b8b7f3a84f11fbdc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 09:05:52 -0800 Subject: [PATCH 072/291] GLES: Use linear for high-res FBO tex copies. --- GPU/GLES/FramebufferManagerGLES.cpp | 2 +- GPU/GLES/StateMappingGLES.cpp | 3 +++ ext/native/thin3d/GLQueueRunner.cpp | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index adf573502f..42015c1169 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -494,7 +494,7 @@ void FramebufferManagerGLES::BlitFramebufferDepth(VirtualFramebuffer *src, Virtu void FramebufferManagerGLES::BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags) { if (!framebuffer->fbo || !useBufferedRendering_) { - render_->BindTexture(0, nullptr); + render_->BindTexture(stage, nullptr); gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE; return; } diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index 65ea0efdc0..a16f7a4e82 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -319,6 +319,9 @@ void DrawEngineGLES::ApplyDrawStateLate(bool setStencil, int stencilValue) { // Note that this is positions, not UVs, that we need the copy from. framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY); framebufferManager_->RebindFramebuffer(); + GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + // If we are rendering at a higher resolution, linear is probably best for the dest color. + renderManager->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); fboTexBound_ = true; fboTexNeedBind_ = false; } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 863398d745..7fc9cb5fdf 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -1056,8 +1056,8 @@ void GLQueueRunner::fbo_ext_create(const GLRInitStep &step) { fbo->color_texture.target = GL_TEXTURE_2D; fbo->color_texture.wrapS = GL_CLAMP_TO_EDGE; fbo->color_texture.wrapT = GL_CLAMP_TO_EDGE; - fbo->color_texture.magFilter = step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST; - fbo->color_texture.minFilter = step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST; + fbo->color_texture.magFilter = GL_LINEAR; + fbo->color_texture.minFilter = GL_LINEAR; fbo->color_texture.maxLod = 0.0f; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, fbo->color_texture.wrapS); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, fbo->color_texture.wrapT); From 2740f74cc48b2a6f10abfab167cba4b2ef48c7b9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 09:09:40 -0800 Subject: [PATCH 073/291] GLES: Add TODO note for shader blend texture. --- GPU/GLES/StateMappingGLES.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index a16f7a4e82..b8a17baf9e 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -317,6 +317,7 @@ void DrawEngineGLES::ApplyDrawStateLate(bool setStencil, int stencilValue) { if (!gstate.isModeClear()) { if (fboTexNeedBind_) { // Note that this is positions, not UVs, that we need the copy from. + // TODO: If the device doesn't support blit, this will corrupt the currently applied texture. framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY); framebufferManager_->RebindFramebuffer(); GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); From 900e53b6dc12e9f71ea709c44c57b9216fe07cc0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 09:17:25 -0800 Subject: [PATCH 074/291] GLES: Re-enable texture scaling. --- GPU/GLES/TextureCacheGLES.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 61e585a8aa..845036945c 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -771,9 +771,12 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_UNKNOWN); } - // TODO: Scale's buffer management doesn't work. - //if (scaleFactor > 1) - // scaler.Scale((uint32_t *)pixelData, dstFmt, w, h, scaleFactor); + if (scaleFactor > 1) { + uint8_t *rearrange = new uint8_t[w * scaleFactor * h * scaleFactor * 4]; + scaler.ScaleAlways((u32 *)rearrange, (u32 *)pixelData, dstFmt, w, h, scaleFactor); + pixelData = rearrange; + delete [] finalBuf; + } if (replacer_.Enabled()) { ReplacedTextureDecodeInfo replacedInfo; From acc3e39b67cb05ef53f0d2694739bbe068b8b926 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 09:35:43 -0800 Subject: [PATCH 075/291] GLES: Reintroduce out of memory checks. --- GPU/GLES/TextureCacheGLES.cpp | 18 +++++++++++++----- ext/native/thin3d/GLQueueRunner.cpp | 21 +++++++++++++++++++++ ext/native/thin3d/GLQueueRunner.h | 6 ++++++ ext/native/thin3d/GLRenderManager.h | 4 ++++ 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 845036945c..59eb3184c1 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -207,6 +207,19 @@ void TextureCacheGLES::StartFrame() { InvalidateLastTexture(); timesInvalidatedAllThisFrame_ = 0; + GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + if (!lowMemoryMode_ && renderManager->SawOutOfMemory()) { + lowMemoryMode_ = true; + decimationCounter_ = 0; + + I18NCategory *err = GetI18NCategory("Error"); + if (standardScaleFactor_ > 1) { + host->NotifyUserMessage(err->T("Warning: Video memory FULL, reducing upscaling and switching to slow caching mode"), 2.0f); + } else { + host->NotifyUserMessage(err->T("Warning: Video memory FULL, switching to slow caching mode"), 2.0f); + } + } + if (texelsScaledThisFrame_) { // INFO_LOG(G3D, "Scaled %i texels", texelsScaledThisFrame_); } @@ -803,11 +816,6 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r // glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, w, h, components2, dstFmt, pixelData); } else { PROFILE_THIS_SCOPE("loadtex"); - // Avoid misleading errors in texture upload, these are common. - GLenum err = glGetError(); - if (err) { - WARN_LOG(G3D, "Got an error BEFORE texture upload: %08x (%s)", err, GLEnumToString(err).c_str()); - } if (IsFakeMipmapChange()) render_->TextureImage(entry.textureName, 0, w, h, components, components2, dstFmt, pixelData); else diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 7fc9cb5fdf..83820ff7e4 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -23,6 +23,9 @@ GLuint g_defaultFBO = 0; void GLQueueRunner::CreateDeviceObjects() { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel_); glGenVertexArrays(1, &globalVAO_); + + // An eternal optimist. + sawOutOfMemory_ = false; } void GLQueueRunner::DestroyDeviceObjects() { @@ -36,6 +39,7 @@ void GLQueueRunner::DestroyDeviceObjects() { void GLQueueRunner::RunInitSteps(const std::vector &steps) { glActiveTexture(GL_TEXTURE0); GLuint boundTexture = (GLuint)-1; + bool allocatedTextures = false; for (int i = 0; i < steps.size(); i++) { const GLRInitStep &step = steps[i]; @@ -197,6 +201,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { { boundTexture = (GLuint)-1; InitCreateFramebuffer(step); + allocatedTextures = true; break; } case GLRInitStepType::TEXTURE_IMAGE: @@ -211,6 +216,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { Crash(); // For things to show in RenderDoc, need to split into glTexImage2D(..., nullptr) and glTexSubImage. glTexImage2D(tex->target, step.texture_image.level, step.texture_image.internalFormat, step.texture_image.width, step.texture_image.height, 0, step.texture_image.format, step.texture_image.type, step.texture_image.data); + allocatedTextures = true; delete[] step.texture_image.data; CHECK_GL_ERROR_IF_DEBUG(); tex->wrapS = GL_CLAMP_TO_EDGE; @@ -242,6 +248,21 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { break; } } + + // TODO: Use GL_KHR_no_error or a debug callback, where supported? + if (allocatedTextures) { + // Users may use replacements or scaling, with high render resolutions, and run out of VRAM. + // This detects that, rather than looking like PPSSPP is broken. + // Calling glGetError() isn't great, but at the end of init shouldn't be too bad... + GLenum err = glGetError(); + if (err == GL_OUT_OF_MEMORY) { + WARN_LOG_REPORT(G3D, "GL ran out of GPU memory; switching to low memory mode"); + sawOutOfMemory_ = true; + } else if (err != GL_NO_ERROR) { + // We checked the err anyway, might as well log if there is one. + WARN_LOG(G3D, "Got an error after init: %08x (%s)", err, GLEnumToString(err).c_str()); + } + } } void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) { diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 498177c178..e04f2f495e 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -328,6 +328,10 @@ public: targetWidth_ = width; targetHeight_ = height; } + + bool SawOutOfMemory() { + return sawOutOfMemory_; + } private: void InitCreateFramebuffer(const GLRInitStep &step); @@ -374,4 +378,6 @@ private: GLuint AllocTextureName(); // Texture name cache. Ripped straight from TextureCacheGLES. std::vector nameCache_; + + bool sawOutOfMemory_ = false; }; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 90502cbb24..abc4fb7ced 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -653,6 +653,10 @@ public: void StopThread(); + bool SawOutOfMemory() { + return queueRunner_.SawOutOfMemory(); + } + private: void BeginSubmitFrame(int frame); void EndSubmitFrame(int frame); From 30a60018a0aa44c3a4f550e2cefa5e311a5c1d33 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 12:05:30 -0800 Subject: [PATCH 076/291] GLES: Fix race crash on shutdown. This happens when there are pointers in step commands that get freed. --- GPU/GLES/GPU_GLES.cpp | 4 ++++ ext/native/thin3d/GLRenderManager.cpp | 27 +++++++++++++++++++++++++++ ext/native/thin3d/GLRenderManager.h | 4 ++++ 3 files changed, 35 insertions(+) diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 5417a24a87..f58c47ddb7 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -184,6 +184,10 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) } GPU_GLES::~GPU_GLES() { + GLRenderManager *render = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + render->Wipe(); + render->WaitUntilQueueIdle(); + framebufferManagerGL_->DestroyAllFBOs(); shaderManagerGL_->ClearCache(true); depalShaderCache_.Clear(); diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 33990e3db1..d272f2571b 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -148,10 +148,12 @@ void GLRenderManager::StopThread() { Crash(); } frameData.readyForRun = false; + frameData.readyForSubmit = false; for (size_t i = 0; i < frameData.steps.size(); i++) { delete frameData.steps[i]; } frameData.steps.clear(); + frameData.initSteps.clear(); std::unique_lock lock(frameData.push_mutex); while (!frameData.readyForFence) { @@ -306,6 +308,7 @@ void GLRenderManager::BeginFrame() { frameData.push_condVar.wait(lock); } frameData.readyForFence = false; + frameData.readyForSubmit = true; } VLOG("PUSH: Fencing %d", curFrame); @@ -381,7 +384,9 @@ void GLRenderManager::Submit(int frame, bool triggerFence) { VLOG("PULL: Frame %d.readyForFence = true", frame); std::unique_lock lock(frameData.push_mutex); + assert(frameData.readyForSubmit); frameData.readyForFence = true; + frameData.readyForSubmit = false; frameData.push_condVar.notify_all(); } } @@ -466,6 +471,7 @@ void GLRenderManager::FlushSync() { frameData.push_condVar.wait(lock); } frameData.readyForFence = false; + frameData.readyForSubmit = true; } } @@ -484,17 +490,38 @@ void GLRenderManager::EndSyncFrame(int frame) { if (useThread_) { std::unique_lock lock(frameData.push_mutex); frameData.readyForFence = true; + frameData.readyForSubmit = true; frameData.push_condVar.notify_all(); } } void GLRenderManager::Wipe() { + initSteps_.clear(); for (auto step : steps_) { delete step; } steps_.clear(); } +void GLRenderManager::WaitUntilQueueIdle() { + if (!useThread_) { + // Must be idle, nothing to do. + return; + } + + // Just wait for all frames to be ready. + for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { + FrameData &frameData = frameData_[i]; + + std::unique_lock lock(frameData.push_mutex); + // Ignore unsubmitted frames. + while (!frameData.readyForFence && !frameData.readyForSubmit) { + VLOG("PUSH: Waiting for frame[%d].readyForFence = 1 (wait idle)", i); + frameData.push_condVar.wait(lock); + } + } +} + GLPushBuffer::GLPushBuffer(GLRenderManager *render, GLuint target, size_t size) : render_(render), target_(target), size_(size) { bool res = AddBuffer(); assert(res); diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index abc4fb7ced..703cda773f 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -211,6 +211,9 @@ public: // Zaps queued up commands. Use if you know there's a risk you've queued up stuff that has already been deleted. Can happen during in-game shutdown. void Wipe(); + // Wait until no frames are pending. Use during shutdown before freeing pointers. + void WaitUntilQueueIdle(); + // Creation commands. These were not needed in Vulkan since there we can do that on the main thread. GLRTexture *CreateTexture(GLenum target) { GLRInitStep step{ GLRInitStepType::CREATE_TEXTURE }; @@ -676,6 +679,7 @@ private: bool readyForFence = true; bool readyForRun = false; + bool readyForSubmit = false; bool skipSwap = false; GLRRunType type = GLRRunType::END; From 7f0b35cd23684fd868ecb6a1c45a2763021f3b81 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 16:44:36 -0800 Subject: [PATCH 077/291] GLES: Run ThreadFrame until frame complete. This makes it easier for frontends that need to call this between other things to handle vsync, or etc. --- ext/native/thin3d/GLRenderManager.cpp | 54 ++++++++++++++------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index d272f2571b..2792e76d1a 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -79,38 +79,42 @@ bool GLRenderManager::ThreadFrame() { std::unique_lock lock(mutex_); if (!run_) return false; - { + + // In case of syncs or other partial completion, we keep going until we complete a frame. + do { if (nextFrame) { threadFrame_++; if (threadFrame_ >= MAX_INFLIGHT_FRAMES) threadFrame_ = 0; } FrameData &frameData = frameData_[threadFrame_]; - std::unique_lock lock(frameData.pull_mutex); - while (!frameData.readyForRun && run_) { - VLOG("PULL: Waiting for frame[%d].readyForRun", threadFrame_); - frameData.pull_condVar.wait(lock); - } - if (!frameData.readyForRun && !run_) { - // This means we're out of frames to render and run_ is false, so bail. - return false; - } - VLOG("PULL: frame[%d].readyForRun = false", threadFrame_); - frameData.readyForRun = false; - // Previously we had a quick exit here that avoided calling Run() if run_ was suddenly false, - // but that created a race condition where frames could end up not finished properly on resize etc. + { + std::unique_lock lock(frameData.pull_mutex); + while (!frameData.readyForRun && run_) { + VLOG("PULL: Waiting for frame[%d].readyForRun", threadFrame_); + frameData.pull_condVar.wait(lock); + } + if (!frameData.readyForRun && !run_) { + // This means we're out of frames to render and run_ is false, so bail. + return false; + } + VLOG("PULL: frame[%d].readyForRun = false", threadFrame_); + frameData.readyForRun = false; + // Previously we had a quick exit here that avoided calling Run() if run_ was suddenly false, + // but that created a race condition where frames could end up not finished properly on resize etc. - // Only increment next time if we're done. - nextFrame = frameData.type == GLRRunType::END; - assert(frameData.type == GLRRunType::END || frameData.type == GLRRunType::SYNC); - } - VLOG("PULL: Running frame %d", threadFrame_); - if (firstFrame) { - ILOG("Running first frame (%d)", threadFrame_); - firstFrame = false; - } - Run(threadFrame_); - VLOG("PULL: Finished frame %d", threadFrame_); + // Only increment next time if we're done. + nextFrame = frameData.type == GLRRunType::END; + assert(frameData.type == GLRRunType::END || frameData.type == GLRRunType::SYNC); + } + VLOG("PULL: Running frame %d", threadFrame_); + if (firstFrame) { + ILOG("Running first frame (%d)", threadFrame_); + firstFrame = false; + } + Run(threadFrame_); + VLOG("PULL: Finished frame %d", threadFrame_); + } while (!nextFrame); return true; } From e280cbbc3cc541e9afced4afb233d8daab16e3f2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 22:56:18 -0800 Subject: [PATCH 078/291] GLES: Correct shader blending. Lunar's spell effects were blending completely wrong, and are a good example of shader blending. This fixes them. --- GPU/GLES/StateMappingGLES.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index b8a17baf9e..caa6ad2472 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -173,6 +173,21 @@ void DrawEngineGLES::ApplyDrawState(int prim) { if (ApplyShaderBlending()) { // We may still want to do something about stencil -> alpha. ApplyStencilReplaceAndLogicOp(blendState.replaceAlphaWithStencil, blendState); + + // We copy the framebuffer here, as doing so will wipe any blend state if we do it later. + if (fboTexNeedBind_) { + // Note that this is positions, not UVs, that we need the copy from. + // TODO: If the device doesn't support blit, this will corrupt the currently applied texture. + framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY); + // If we are rendering at a higher resolution, linear is probably best for the dest color. + renderManager->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); + fboTexBound_ = true; + fboTexNeedBind_ = false; + + framebufferManager_->RebindFramebuffer(); + // Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects. + gstate_c.Dirty(DIRTY_BLEND_STATE); + } } else { // Until next time, force it off. ResetShaderBlending(); @@ -315,18 +330,6 @@ void DrawEngineGLES::ApplyDrawStateLate(bool setStencil, int stencilValue) { // 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()) { - if (fboTexNeedBind_) { - // Note that this is positions, not UVs, that we need the copy from. - // TODO: If the device doesn't support blit, this will corrupt the currently applied texture. - framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY); - framebufferManager_->RebindFramebuffer(); - GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - // If we are rendering at a higher resolution, linear is probably best for the dest color. - renderManager->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); - fboTexBound_ = true; - fboTexNeedBind_ = false; - } - // Apply last, once we know the alpha params of the texture. if (gstate.isAlphaTestEnabled() || gstate.isColorTestEnabled()) { fragmentTestCache_->BindTestTexture(2); From 22f65500f1d65da8d96317c69a981e505cdbf1b5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jan 2018 23:05:28 -0800 Subject: [PATCH 079/291] GPU: Fix shader blending recopying. This at least didn't look horrible like GLEs did, but still looked odd in Lunar. --- GPU/D3D11/StateMappingD3D11.cpp | 4 ++++ GPU/Vulkan/DrawEngineVulkan.cpp | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/GPU/D3D11/StateMappingD3D11.cpp b/GPU/D3D11/StateMappingD3D11.cpp index 002a118fa4..ee76b37322 100644 --- a/GPU/D3D11/StateMappingD3D11.cpp +++ b/GPU/D3D11/StateMappingD3D11.cpp @@ -462,4 +462,8 @@ void DrawEngineD3D11::ApplyDrawStateLate(bool applyStencilRef, uint8_t stencilRe context_->OMSetDepthStencilState(depthStencilState_, applyStencilRef ? stencilRef : dynState_.stencilRef); } gstate_c.Clean(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_BLEND_STATE); + + // Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects. + if (fboTexBound_) + gstate_c.Dirty(DIRTY_BLEND_STATE); } diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index a11e02d27e..6143778ddd 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -847,6 +847,10 @@ void DrawEngineVulkan::DoFlush() { ApplyDrawStateLate(renderManager, false, 0, pipeline->useBlendConstant); gstate_c.Clean(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE); lastPipeline_ = pipeline; + + // Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects. + if (fboTexBound_) + gstate_c.Dirty(DIRTY_BLEND_STATE); } lastPrim_ = prim; @@ -947,6 +951,10 @@ void DrawEngineVulkan::DoFlush() { ApplyDrawStateLate(renderManager, result.setStencil, result.stencilValue, pipeline->useBlendConstant); gstate_c.Clean(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE); lastPipeline_ = pipeline; + + // Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects. + if (fboTexBound_) + gstate_c.Dirty(DIRTY_BLEND_STATE); } lastPrim_ = prim; From 0399088fc772b4b314b4904ad14d81321b8f7e81 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Jan 2018 08:49:34 -0800 Subject: [PATCH 080/291] GLES: Handle glGetString() on GL thread. We only use a few strings, so should be fine to cache them. --- GPU/GLES/GPU_GLES.cpp | 26 ++++++++++---------------- ext/native/thin3d/GLQueueRunner.cpp | 14 ++++++++++++++ ext/native/thin3d/GLQueueRunner.h | 8 ++++++++ ext/native/thin3d/GLRenderManager.h | 5 +++++ ext/native/thin3d/thin3d_gl.cpp | 8 ++++---- 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index f58c47ddb7..4ca8419772 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -365,30 +365,24 @@ bool GPU_GLES::IsReady() { return shaderManagerGL_->ContinuePrecompile(); } -// Let's avoid passing nulls into snprintf(). -static const char *GetGLStringAlways(GLenum name) { - const GLubyte *value = glGetString(name); - if (!value) - return "?"; - return (const char *)value; -} - // Needs to be called on GPU thread, not reporting thread. void GPU_GLES::BuildReportingInfo() { - const char *glVendor = GetGLStringAlways(GL_VENDOR); - const char *glRenderer = GetGLStringAlways(GL_RENDERER); - const char *glVersion = GetGLStringAlways(GL_VERSION); - const char *glSlVersion = GetGLStringAlways(GL_SHADING_LANGUAGE_VERSION); - const char *glExtensions = nullptr; + GLRenderManager *render = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + + std::string glVendor = render->GetGLString(GL_VENDOR); + std::string glRenderer = render->GetGLString(GL_RENDERER); + std::string glVersion = render->GetGLString(GL_VERSION); + std::string glSlVersion = render->GetGLString(GL_SHADING_LANGUAGE_VERSION); + std::string glExtensions; if (gl_extensions.VersionGEThan(3, 0)) { - glExtensions = g_all_gl_extensions.c_str(); + glExtensions = g_all_gl_extensions; } else { - glExtensions = GetGLStringAlways(GL_EXTENSIONS); + glExtensions = render->GetGLString(GL_EXTENSIONS); } char temp[16384]; - snprintf(temp, sizeof(temp), "%s (%s %s), %s (extensions: %s)", glVersion, glVendor, glRenderer, glSlVersion, glExtensions); + snprintf(temp, sizeof(temp), "%s (%s %s), %s (extensions: %s)", glVersion.c_str(), glVendor.c_str(), glRenderer.c_str(), glSlVersion.c_str(), glExtensions.c_str()); reportingPrimaryInfo_ = glVendor; reportingFullInfo_ = temp; diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 83820ff7e4..a7072931bb 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -26,6 +26,20 @@ void GLQueueRunner::CreateDeviceObjects() { // An eternal optimist. sawOutOfMemory_ = false; + + // Populate some strings from the GL thread. + auto populate = [&](int name) { + const GLubyte *value = glGetString(name); + if (!value) + glStrings_[name] = "?"; + else + glStrings_[name] = (const char *)value; + }; + populate(GL_VENDOR); + populate(GL_RENDERER); + populate(GL_VERSION); + populate(GL_SHADING_LANGUAGE_VERSION); + populate(GL_EXTENSIONS); } void GLQueueRunner::DestroyDeviceObjects() { diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index e04f2f495e..511e3425a1 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -2,6 +2,7 @@ #include #include +#include #include "gfx/gl_common.h" #include "thin3d/DataFormat.h" @@ -332,6 +333,12 @@ public: bool SawOutOfMemory() { return sawOutOfMemory_; } + + std::string GetGLString(int name) const { + auto it = glStrings_.find(name); + return it != glStrings_.end() ? it->second : ""; + } + private: void InitCreateFramebuffer(const GLRInitStep &step); @@ -378,6 +385,7 @@ private: GLuint AllocTextureName(); // Texture name cache. Ripped straight from TextureCacheGLES. std::vector nameCache_; + std::unordered_map glStrings_; bool sawOutOfMemory_ = false; }; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 703cda773f..6bd2d7caf1 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -660,6 +660,11 @@ public: return queueRunner_.SawOutOfMemory(); } + // Only supports a common subset. + std::string GetGLString(int name) const { + return queueRunner_.GetGLString(name); + } + private: void BeginSubmitFrame(int frame); void EndSubmitFrame(int frame); diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index a16411fbe7..b831e199a0 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -435,7 +435,7 @@ public: } else { return "OpenGL"; } - case VENDORSTRING: return (const char *)glGetString(GL_VENDOR); + case VENDORSTRING: return renderManager_.GetGLString(GL_VENDOR); case VENDOR: switch (caps_.vendor) { case GPUVendor::VENDOR_AMD: return "VENDOR_AMD"; @@ -450,9 +450,9 @@ public: return "VENDOR_UNKNOWN"; } break; - case DRIVER: return (const char *)glGetString(GL_RENDERER); - case SHADELANGVERSION: return (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); - case APIVERSION: return (const char *)glGetString(GL_VERSION); + case DRIVER: return renderManager_.GetGLString(GL_RENDERER); + case SHADELANGVERSION: return renderManager_.GetGLString(GL_SHADING_LANGUAGE_VERSION); + case APIVERSION: return renderManager_.GetGLString(GL_VERSION); default: return "?"; } } From 59904c316bf33b148f8d66c88d05ee5c20ec07b8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Jan 2018 09:03:19 -0800 Subject: [PATCH 081/291] SDL: Allow running GL on thread. Tested on a Mac. --- SDL/SDLMain.cpp | 86 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 6 deletions(-) diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index acc5cc0e10..7770682204 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -14,9 +14,11 @@ SDLJoystick *joystick = NULL; #include #endif +#include #include #include #include +#include #include "base/display.h" #include "base/logging.h" @@ -32,6 +34,7 @@ SDLJoystick *joystick = NULL; #include "util/text/utf8.h" #include "util/text/parsers.h" #include "math/math_util.h" +#include "thin3d/GLRenderManager.h" #include "Common/Vulkan/VulkanContext.h" #include "Common/Vulkan/VulkanDebug.h" #include "math.h" @@ -198,6 +201,8 @@ void EGL_Close() { } #endif +class GLRenderManager; + class SDLGLGraphicsContext : public DummyGraphicsContext { public: SDLGLGraphicsContext() { @@ -218,21 +223,30 @@ public: } void SwapBuffers() override { -#ifdef USING_EGL - eglSwapBuffers(g_eglDisplay, g_eglSurface); -#else - SDL_GL_SwapWindow(window_); -#endif + renderManager_->Swap(); } Draw::DrawContext *GetDrawContext() override { return draw_; } + void ThreadStart() override { + renderManager_->ThreadStart(); + } + + bool ThreadFrame() override { + return renderManager_->ThreadFrame(); + } + + void ThreadEnd() override { + renderManager_->ThreadEnd(); + } + private: Draw::DrawContext *draw_ = nullptr; SDL_Window *window_; SDL_GLContext glContext = nullptr; + GLRenderManager *renderManager_ = nullptr; }; // Returns 0 on success. @@ -340,9 +354,17 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std: // Finally we can do the regular initialization. CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); + renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); assert(success); + renderManager_->SetSwapFunction([&]() { +#ifdef USING_EGL + eglSwapBuffers(g_eglDisplay, g_eglSurface); +#else + SDL_GL_SwapWindow(window_); +#endif + }); window_ = window; return 0; } @@ -691,6 +713,38 @@ void ToggleFullScreenIfFlagSet(SDL_Window *window) { } } +enum class EmuThreadState { + DISABLED, + START_REQUESTED, + RUNNING, + QUIT_REQUESTED, + STOPPED, +}; + +static std::thread emuThread; +static std::atomic emuThreadState((int)EmuThreadState::DISABLED); + +static void EmuThreadFunc() { + // There's no real requirement that NativeInit happen on this thread. + // We just call the update/render loop here. + emuThreadState = (int)EmuThreadState::RUNNING; + while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) { + UpdateRunLoop(); + } + emuThreadState = (int)EmuThreadState::STOPPED; +} + +static void EmuThreadStart() { + emuThreadState = (int)EmuThreadState::START_REQUESTED; + emuThread = std::thread(&EmuThreadFunc); +} + +static void EmuThreadStop() { + emuThreadState = (int)EmuThreadState::QUIT_REQUESTED; + emuThread.join(); + emuThread = std::thread(); +} + #ifdef _WIN32 #undef main #endif @@ -888,6 +942,11 @@ int main(int argc, char *argv[]) { } } + // Since we render from the main thread, there's nothing done here, but we call it to avoid confusion. + if (!graphicsContext->InitFromRenderThread(&error_message)) { + printf("Init from thread error: '%s'\n", error_message.c_str()); + } + SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); #ifdef MOBILE_DEVICE @@ -934,6 +993,9 @@ int main(int argc, char *argv[]) { int framecount = 0; bool mouseDown = false; + EmuThreadStart(); + graphicsContext->ThreadStart(); + while (true) { SDL_Event event; while (SDL_PollEvent(&event)) { @@ -1101,7 +1163,9 @@ int main(int argc, char *argv[]) { if (g_QuitRequested) break; const uint8_t *keys = SDL_GetKeyboardState(NULL); - UpdateRunLoop(); + if (emuThreadState == (int)EmuThreadState::DISABLED) { + UpdateRunLoop(); + } if (g_QuitRequested) break; #if !defined(MOBILE_DEVICE) @@ -1118,12 +1182,22 @@ int main(int argc, char *argv[]) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } + if (emuThreadState != (int)EmuThreadState::DISABLED) { + if (!graphicsContext->ThreadFrame()) + break; + } graphicsContext->SwapBuffers(); ToggleFullScreenIfFlagSet(window); time_update(); framecount++; } + + graphicsContext->ThreadEnd(); + graphicsContext->ShutdownFromRenderThread(); + + EmuThreadStop(); + delete joystick; NativeShutdownGraphics(); graphicsContext->Shutdown(); From 95bcda409d7b6ff4e538801f8717ac2c77bcc803 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Jan 2018 09:17:24 -0800 Subject: [PATCH 082/291] GLES: Fix segfault on GL 2.x. --- ext/native/thin3d/GLQueueRunner.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index a7072931bb..a895ed4649 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -22,7 +22,9 @@ GLuint g_defaultFBO = 0; void GLQueueRunner::CreateDeviceObjects() { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel_); - glGenVertexArrays(1, &globalVAO_); + if (gl_extensions.ARB_vertex_array_object) { + glGenVertexArrays(1, &globalVAO_); + } // An eternal optimist. sawOutOfMemory_ = false; @@ -47,7 +49,9 @@ void GLQueueRunner::DestroyDeviceObjects() { glDeleteTextures((GLsizei)nameCache_.size(), &nameCache_[0]); nameCache_.clear(); } - glDeleteVertexArrays(1, &globalVAO_); + if (gl_extensions.ARB_vertex_array_object) { + glDeleteVertexArrays(1, &globalVAO_); + } } void GLQueueRunner::RunInitSteps(const std::vector &steps) { @@ -479,7 +483,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { #endif */ - glBindVertexArray(globalVAO_); + if (gl_extensions.ARB_vertex_array_object) { + glBindVertexArray(globalVAO_); + } GLRFramebuffer *fb = step.render.framebuffer; GLRProgram *curProgram = nullptr; @@ -889,7 +895,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { // Wipe out the current state. glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); + if (gl_extensions.ARB_vertex_array_object) { + glBindVertexArray(0); + } glDisable(GL_SCISSOR_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); From 062566b67cb0822710e69b8b6f3ab90a62d90eff Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Jan 2018 09:47:07 -0800 Subject: [PATCH 083/291] Core: Set thread names when possible. This doesn't seem to be working for lldb, though. --- SDL/SDLMain.cpp | 3 +++ ext/native/thread/threadutil.cpp | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 7770682204..38fcfc4203 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -35,6 +35,7 @@ SDLJoystick *joystick = NULL; #include "util/text/parsers.h" #include "math/math_util.h" #include "thin3d/GLRenderManager.h" +#include "thread/threadutil.h" #include "Common/Vulkan/VulkanContext.h" #include "Common/Vulkan/VulkanDebug.h" #include "math.h" @@ -725,6 +726,8 @@ static std::thread emuThread; static std::atomic emuThreadState((int)EmuThreadState::DISABLED); static void EmuThreadFunc() { + setCurrentThreadName("Emu"); + // There's no real requirement that NativeInit happen on this thread. // We just call the update/render loop here. emuThreadState = (int)EmuThreadState::RUNNING; diff --git a/ext/native/thread/threadutil.cpp b/ext/native/thread/threadutil.cpp index fcd050e98f..403f8cadd9 100644 --- a/ext/native/thread/threadutil.cpp +++ b/ext/native/thread/threadutil.cpp @@ -12,7 +12,7 @@ #include "base/logging.h" #include "thread/threadutil.h" -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__APPLE__) || (defined(__GLIBC__) && defined(_GNU_SOURCE)) #include #endif @@ -96,10 +96,12 @@ void setCurrentThreadName(const char* threadName) { {} #else -#if defined(__ANDROID__) +#if defined(__ANDROID__) || (defined(__GLIBC__) && defined(_GNU_SOURCE)) pthread_setname_np(pthread_self(), threadName); +#elif defined(__APPLE__) + pthread_setname_np(threadName); // #else -// pthread_setname_np(thread_name); +// pthread_setname_np(threadName); #endif // Do nothing From 56a18907ddf29c56db65f38a75c21afcace78b32 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Jan 2018 11:02:22 -0800 Subject: [PATCH 084/291] SDL: Oops, only start the emu thread for GLES. Probably would've caused issues (at least weird vsync) for Vulkan. --- SDL/SDLMain.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 38fcfc4203..a3a15581e0 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -996,7 +996,9 @@ int main(int argc, char *argv[]) { int framecount = 0; bool mouseDown = false; - EmuThreadStart(); + if (GetGPUBackend() == GPUBackend::OPENGL) { + EmuThreadStart(); + } graphicsContext->ThreadStart(); while (true) { From 0943cf3fcc246215b4d15438733064d69448d054 Mon Sep 17 00:00:00 2001 From: Kentucky Compass Date: Mon, 22 Jan 2018 00:15:41 -0800 Subject: [PATCH 085/291] use GLRenderManager on iOS --- ios/ViewController.mm | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 2ec8d7e7a7..b381b15bb3 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -16,6 +16,7 @@ #include "net/resolve.h" #include "ui/screen.h" #include "thin3d/thin3d.h" +#include "thin3d/GLRenderManager.h" #include "input/keycodes.h" #include "gfx_es2/gpu_features.h" @@ -30,23 +31,36 @@ #define IS_IPAD() ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) #define IS_IPHONE() ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) -class IOSDummyGraphicsContext : public DummyGraphicsContext { +class IOSGraphicsContext : public DummyGraphicsContext { public: - IOSDummyGraphicsContext() { + IOSGraphicsContext() { CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); + renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); assert(success); } - ~IOSDummyGraphicsContext() { + ~IOSGraphicsContext() { delete draw_; } Draw::DrawContext *GetDrawContext() override { return draw_; } + void ThreadStart() override { + renderManager_->ThreadStart(); + } + + bool ThreadFrame() override { + return renderManager_->ThreadFrame(); + } + + void ThreadEnd() override { + renderManager_->ThreadEnd(); + } private: Draw::DrawContext *draw_; + GLRenderManager *renderManager_; }; static float dp_xscale = 1.0f; @@ -55,6 +69,7 @@ static float dp_yscale = 1.0f; static double lastSelectPress = 0.0f; static double lastStartPress = 0.0f; static bool simulateAnalog = false; +static bool threadEnabled = true; __unsafe_unretained static ViewController* sharedViewController; static GraphicsContext *graphicsContext; @@ -153,9 +168,10 @@ static GraphicsContext *graphicsContext; pixel_in_dps_x = (float)pixel_xres / (float)dp_xres; pixel_in_dps_y = (float)pixel_yres / (float)dp_yres; - graphicsContext = new IOSDummyGraphicsContext(); - + graphicsContext = new IOSGraphicsContext(); + NativeInitGraphics(graphicsContext); + graphicsContext->ThreadStart(); dp_xscale = (float)dp_xres / (float)pixel_xres; dp_yscale = (float)dp_yres / (float)pixel_yres; @@ -172,6 +188,14 @@ static GraphicsContext *graphicsContext; } } #endif + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + while (threadEnabled) { + NativeUpdate(); + NativeRender(graphicsContext); + time_update(); + } + }); } - (void)didReceiveMemoryWarning @@ -195,6 +219,7 @@ static GraphicsContext *graphicsContext; self.gameController = nil; } #endif + graphicsContext->ThreadEnd(); NativeShutdownGraphics(); graphicsContext->Shutdown(); delete graphicsContext; @@ -216,9 +241,7 @@ static GraphicsContext *graphicsContext; - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { - NativeUpdate(); - NativeRender(graphicsContext); - time_update(); + graphicsContext->ThreadFrame(); } - (void)touchX:(float)x y:(float)y code:(int)code pointerId:(int)pointerId From 49c5880fccec11210977229d2b00650f84b4d68c Mon Sep 17 00:00:00 2001 From: Kentucky Compass Date: Mon, 22 Jan 2018 00:25:34 -0800 Subject: [PATCH 086/291] disable the iOS thread before shutting down --- ios/ViewController.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/ios/ViewController.mm b/ios/ViewController.mm index b381b15bb3..d8b6d79f12 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -219,6 +219,7 @@ static GraphicsContext *graphicsContext; self.gameController = nil; } #endif + threadEnabled = false; graphicsContext->ThreadEnd(); NativeShutdownGraphics(); graphicsContext->Shutdown(); From d43283239d4339a13368b988f747421609c07166 Mon Sep 17 00:00:00 2001 From: Kentucky Compass Date: Tue, 23 Jan 2018 01:28:16 -0800 Subject: [PATCH 087/291] whitespace cleanup --- ios/ViewController.mm | 48 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/ios/ViewController.mm b/ios/ViewController.mm index d8b6d79f12..050202ec95 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -47,20 +47,20 @@ public: Draw::DrawContext *GetDrawContext() override { return draw_; } - void ThreadStart() override { - renderManager_->ThreadStart(); - } - - bool ThreadFrame() override { - return renderManager_->ThreadFrame(); - } - - void ThreadEnd() override { - renderManager_->ThreadEnd(); - } + void ThreadStart() override { + renderManager_->ThreadStart(); + } + + bool ThreadFrame() override { + return renderManager_->ThreadFrame(); + } + + void ThreadEnd() override { + renderManager_->ThreadEnd(); + } private: Draw::DrawContext *draw_; - GLRenderManager *renderManager_; + GLRenderManager *renderManager_; }; static float dp_xscale = 1.0f; @@ -169,7 +169,7 @@ static GraphicsContext *graphicsContext; pixel_in_dps_y = (float)pixel_yres / (float)dp_yres; graphicsContext = new IOSGraphicsContext(); - + NativeInitGraphics(graphicsContext); graphicsContext->ThreadStart(); @@ -188,14 +188,14 @@ static GraphicsContext *graphicsContext; } } #endif - - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ - while (threadEnabled) { - NativeUpdate(); - NativeRender(graphicsContext); - time_update(); - } - }); + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + while (threadEnabled) { + NativeUpdate(); + NativeRender(graphicsContext); + time_update(); + } + }); } - (void)didReceiveMemoryWarning @@ -219,8 +219,8 @@ static GraphicsContext *graphicsContext; self.gameController = nil; } #endif - threadEnabled = false; - graphicsContext->ThreadEnd(); + threadEnabled = false; + graphicsContext->ThreadEnd(); NativeShutdownGraphics(); graphicsContext->Shutdown(); delete graphicsContext; @@ -242,7 +242,7 @@ static GraphicsContext *graphicsContext; - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { - graphicsContext->ThreadFrame(); + graphicsContext->ThreadFrame(); } - (void)touchX:(float)x y:(float)y code:(int)code pointerId:(int)pointerId From c5a09de446c9cb299f7ef27879b956b329ad2404 Mon Sep 17 00:00:00 2001 From: Kentucky Compass Date: Tue, 23 Jan 2018 01:30:58 -0800 Subject: [PATCH 088/291] one more whitespace fix --- ios/ViewController.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 050202ec95..064a89df33 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -36,7 +36,7 @@ public: IOSGraphicsContext() { CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); - renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); assert(success); From e7c9afd7bbc5934570b629d702f6ae735715d305 Mon Sep 17 00:00:00 2001 From: Kentucky Compass Date: Tue, 23 Jan 2018 01:33:02 -0800 Subject: [PATCH 089/291] another whitespace fix --- ios/ViewController.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 064a89df33..a214286791 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -171,7 +171,7 @@ static GraphicsContext *graphicsContext; graphicsContext = new IOSGraphicsContext(); NativeInitGraphics(graphicsContext); - graphicsContext->ThreadStart(); + graphicsContext->ThreadStart(); dp_xscale = (float)dp_xres / (float)pixel_xres; dp_yscale = (float)dp_yres / (float)pixel_yres; From 7abb8702ce562b6e6e67fd1f3f0c72c8478491a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 20 Jan 2018 20:29:18 +0100 Subject: [PATCH 090/291] Work towards threaded GL on Android. Now TextDrawer barfs on wrong JNI context. --- android/jni/AndroidEGLContext.cpp | 7 +- android/jni/AndroidEGLContext.h | 2 +- android/jni/AndroidGraphicsContext.h | 4 +- android/jni/AndroidJavaGLContext.cpp | 21 ++- android/jni/AndroidJavaGLContext.h | 29 +++- android/jni/AndroidVulkanContext.cpp | 7 +- android/jni/AndroidVulkanContext.h | 2 +- android/jni/app-android.cpp | 148 +++++++++++++----- .../org/ppsspp/ppsspp/NativeSurfaceView.java | 2 +- 9 files changed, 172 insertions(+), 50 deletions(-) diff --git a/android/jni/AndroidEGLContext.cpp b/android/jni/AndroidEGLContext.cpp index 8742085535..c9b5d81251 100644 --- a/android/jni/AndroidEGLContext.cpp +++ b/android/jni/AndroidEGLContext.cpp @@ -6,13 +6,18 @@ #include "GL/GLInterface/EGLAndroid.h" #include "Core/System.h" -bool AndroidEGLGraphicsContext::Init(ANativeWindow *wnd, int backbufferWidth, int backbufferHeight, int backbufferFormat, int androidVersion) { +bool AndroidEGLGraphicsContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, + int desiredBackbufferSizeY, + int backbufferFormat, int androidVersion) { + ILOG("AndroidEGLGraphicsContext::Init()"); wnd_ = wnd; gl = HostGL_CreateGLInterface(); if (!gl) { ELOG("ERROR: Failed to create GL interface"); return false; } + int backbufferWidth = desiredBackbufferSizeX; + int backbufferHeight = desiredBackbufferSizeY; ILOG("EGL interface created. Desired backbuffer size: %dx%d", backbufferWidth, backbufferHeight); // Apparently we still have to set this through Java through setFixedSize on the bufferHolder for it to take effect... diff --git a/android/jni/AndroidEGLContext.h b/android/jni/AndroidEGLContext.h index efeafecf80..fd86bc6cfe 100644 --- a/android/jni/AndroidEGLContext.h +++ b/android/jni/AndroidEGLContext.h @@ -6,7 +6,7 @@ class AndroidEGLGraphicsContext : public AndroidGraphicsContext { public: AndroidEGLGraphicsContext() : draw_(nullptr), wnd_(nullptr), gl(nullptr) {} - bool Init(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) override; + bool InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) override; void Shutdown() override; void SwapBuffers() override; void SwapInterval(int interval) override {} diff --git a/android/jni/AndroidGraphicsContext.h b/android/jni/AndroidGraphicsContext.h index 027be92505..72279b7d6d 100644 --- a/android/jni/AndroidGraphicsContext.h +++ b/android/jni/AndroidGraphicsContext.h @@ -19,5 +19,7 @@ enum { class AndroidGraphicsContext : public GraphicsContext { public: - virtual bool Init(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) = 0; + // This is different than the base class function since on + // Android (EGL, Vulkan) we do have all this info on the render thread. + virtual bool InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) {} }; diff --git a/android/jni/AndroidJavaGLContext.cpp b/android/jni/AndroidJavaGLContext.cpp index 8a97a62187..70dc543a4c 100644 --- a/android/jni/AndroidJavaGLContext.cpp +++ b/android/jni/AndroidJavaGLContext.cpp @@ -4,16 +4,25 @@ #include "Core/System.h" AndroidJavaEGLGraphicsContext::AndroidJavaEGLGraphicsContext() { + SetGPUBackend(GPUBackend::OPENGL); +} + +bool AndroidJavaEGLGraphicsContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) { + ILOG("AndroidJavaEGLGraphicsContext::InitFromRenderThread"); CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); - SetGPUBackend(GPUBackend::OPENGL); + renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); bool success = draw_->CreatePresets(); - assert(success); + return success; +} + +void AndroidJavaEGLGraphicsContext::ShutdownFromRenderThread() { + ILOG("AndroidJavaEGLGraphicsContext::Shutdown"); + renderManager_ = nullptr; // owned by draw_. + delete draw_; + draw_ = nullptr; } void AndroidJavaEGLGraphicsContext::Shutdown() { - ILOG("AndroidJavaEGLGraphicsContext::Shutdown"); - delete draw_; - draw_ = nullptr; - NativeShutdownGraphics(); + // TODO } diff --git a/android/jni/AndroidJavaGLContext.h b/android/jni/AndroidJavaGLContext.h index 36e443e51d..c6e11910e7 100644 --- a/android/jni/AndroidJavaGLContext.h +++ b/android/jni/AndroidJavaGLContext.h @@ -1,14 +1,25 @@ #pragma once +#include +#include +#include + #include "AndroidGraphicsContext.h" +#include "thin3d/GLRenderManager.h" // Doesn't do much. Just to fit in. -class AndroidJavaEGLGraphicsContext : public GraphicsContext { +class AndroidJavaEGLGraphicsContext : public AndroidGraphicsContext { public: AndroidJavaEGLGraphicsContext(); ~AndroidJavaEGLGraphicsContext() { delete draw_; } + + // This performs the actual initialization, + bool InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) override; + + void ShutdownFromRenderThread() override; + void Shutdown() override; void SwapBuffers() override {} void SwapInterval(int interval) override {} @@ -16,7 +27,21 @@ public: Draw::DrawContext *GetDrawContext() override { return draw_; } + + void ThreadStart() override { + renderManager_->ThreadStart(); + } + + bool ThreadFrame() override { + return renderManager_->ThreadFrame(); + } + + void ThreadEnd() override { + renderManager_->ThreadEnd(); + } + private: - Draw::DrawContext *draw_; + Draw::DrawContext *draw_ = nullptr; + GLRenderManager *renderManager_ = nullptr; }; diff --git a/android/jni/AndroidVulkanContext.cpp b/android/jni/AndroidVulkanContext.cpp index 99b21469be..29ad3f3103 100644 --- a/android/jni/AndroidVulkanContext.cpp +++ b/android/jni/AndroidVulkanContext.cpp @@ -58,7 +58,8 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, loglevel = ANDROID_LOG_WARN; } - __android_log_print(loglevel, APP_NAME, "[%s] %s Code %d : %s", pLayerPrefix, ObjTypeToString(objType), msgCode, pMsg); + __android_log_print(loglevel, APP_NAME, "[%s] %s Code %d : %s", + pLayerPrefix, ObjTypeToString(objType), msgCode, pMsg); // false indicates that layer should not bail-out of an // API call that had validation failures. This may mean that the @@ -73,7 +74,9 @@ AndroidVulkanContext::~AndroidVulkanContext() { g_Vulkan = nullptr; } -bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) { +bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, + int desiredBackbufferSizeY, int backbufferFormat, + int androidVersion) { ILOG("AndroidVulkanContext::Init"); init_glslang(); diff --git a/android/jni/AndroidVulkanContext.h b/android/jni/AndroidVulkanContext.h index 8c48e09c92..e43041d3dc 100644 --- a/android/jni/AndroidVulkanContext.h +++ b/android/jni/AndroidVulkanContext.h @@ -11,7 +11,7 @@ public: AndroidVulkanContext() : draw_(nullptr) {} ~AndroidVulkanContext(); - bool Init(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) override; + bool InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) override; void Shutdown() override; void SwapInterval(int interval) override; void SwapBuffers() override; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 97ce69edc4..819d88468c 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,21 @@ JNIEnv *jniEnvMain; JNIEnv *jniEnvGraphics; JavaVM *javaVM; +bool useCPUThread = true; + +enum class EmuThreadState { + DISABLED, + START_REQUESTED, + RUNNING, + QUIT_REQUESTED, + STOPPED, +}; + +static std::thread emuThread; +static std::atomic emuThreadState((int)EmuThreadState::DISABLED); + +void UpdateRunLoopAndroid(JNIEnv *env); + static AndroidAudioState *g_audioState; struct FrameCommand { @@ -114,7 +130,33 @@ static bool javaGL = true; static std::string library_path; static std::map permissions; -GraphicsContext *graphicsContext; +AndroidGraphicsContext *graphicsContext; + +static void EmuThreadFunc(JavaVM *vm) { + JNIEnv *env; + vm->AttachCurrentThread(&env, nullptr); + // There's no real requirement that NativeInit happen on this thread. + // We just call the update/render loop here. + emuThreadState = (int)EmuThreadState::RUNNING; + while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) { + UpdateRunLoopAndroid(env); + } + emuThreadState = (int)EmuThreadState::STOPPED; + vm->DetachCurrentThread(); +} + +static void EmuThreadStart(JNIEnv *env) { + emuThreadState = (int)EmuThreadState::START_REQUESTED; + JavaVM *vm; + env->GetJavaVM(&vm); + emuThread = std::thread(&EmuThreadFunc, vm); +} + +static void EmuThreadStop() { + emuThreadState = (int)EmuThreadState::QUIT_REQUESTED; + emuThread.join(); + emuThread = std::thread(); +} static void ProcessFrameCommands(JNIEnv *env); @@ -225,7 +267,6 @@ std::string GetJavaString(JNIEnv *env, jstring jstr) { extern "C" void Java_org_ppsspp_ppsspp_NativeActivity_registerCallbacks(JNIEnv *env, jobject obj) { nativeActivity = env->NewGlobalRef(obj); postCommand = env->GetMethodID(env->GetObjectClass(obj), "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); - ILOG("Got method ID to postCommand: %p", postCommand); } extern "C" void Java_org_ppsspp_ppsspp_NativeActivity_unregisterCallbacks(JNIEnv *env, jobject obj) { @@ -323,8 +364,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init if (shortcut_param.empty()) { const char *argv[2] = {app_name.c_str(), 0}; NativeInit(1, argv, user_data_path.c_str(), externalDir.c_str(), cacheDir.c_str()); - } - else { + } else { const char *argv[3] = {app_name.c_str(), shortcut_param.c_str(), 0}; NativeInit(2, argv, user_data_path.c_str(), externalDir.c_str(), cacheDir.c_str()); } @@ -332,6 +372,33 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init // Now that we've loaded config, set javaGL. javaGL = NativeQueryConfig("androidJavaGL") == "true"; +retry: + switch (g_Config.iGPUBackend) { + case (int)GPUBackend::OPENGL: + ILOG("NativeApp.init() -- creating OpenGL context"); + useCPUThread = true; + if (javaGL) { + graphicsContext = new AndroidJavaEGLGraphicsContext(); + } else { + graphicsContext = new AndroidEGLGraphicsContext(); + } + break; + case (int)GPUBackend::VULKAN: + ILOG("NativeApp.init() -- creating Vulkan context"); + useCPUThread = false; // The Vulkan render manager manages its own thread. + graphicsContext = new AndroidVulkanContext(); + break; + default: + ELOG("NativeApp.init(): iGPUBackend %d not supported. Switching to OpenGL.", (int)g_Config.iGPUBackend); + g_Config.iGPUBackend = (int)GPUBackend::OPENGL; + goto retry; + // Crash(); + } + + if (useCPUThread) { + ILOG("NativeApp.init() - launching emu thread"); + EmuThreadStart(env); + } ILOG("NativeApp.init() -- end"); } @@ -381,9 +448,13 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_pause(JNIEnv *, jclass) { } extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { + if (useCPUThread) + EmuThreadStop(); + ILOG("NativeApp.shutdown() -- begin"); if (renderer_inited) { ILOG("Shutting down renderer"); + // This will be from the wrong thread? :/ graphicsContext->Shutdown(); delete graphicsContext; graphicsContext = nullptr; @@ -407,26 +478,26 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, ELOG("GetEnv failed: %d", res); } - if (javaGL && !graphicsContext) { - graphicsContext = new AndroidJavaEGLGraphicsContext(); - } else if (!graphicsContext) { - _assert_msg_(G3D, false, "No graphics context in displayInit?"); - } + if (!graphicsContext) + Crash(); + // We should be running on the render thread here. + std::string errorMessage; if (renderer_inited) { ILOG("NativeApp.displayInit() restoring"); - NativeShutdownGraphics(); - delete graphicsContext; + graphicsContext->ThreadEnd(); + graphicsContext->ShutdownFromRenderThread(); - graphicsContext = new AndroidJavaEGLGraphicsContext(); - NativeInitGraphics(graphicsContext); + graphicsContext->InitFromRenderThread(nullptr, 0, 0, 0, 0); + graphicsContext->ThreadStart(); ILOG("Restored."); } else { ILOG("NativeApp.displayInit() first time"); + graphicsContext->InitFromRenderThread(nullptr, 0, 0, 0, 0); + graphicsContext->ThreadStart(); NativeInitGraphics(graphicsContext); renderer_inited = true; } - NativeMessageReceived("recreateviews", ""); } @@ -470,23 +541,19 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv } } -// JavaEGL -extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { - static bool hasSetThreadName = false; - if (!hasSetThreadName) { - hasSetThreadName = true; - setCurrentThreadName("AndroidRender"); +void UpdateRunLoopAndroid(JNIEnv *env) { + // Wait for render loop to get started. + if (!renderer_inited) { + ILOG("Runloop: Waiting for displayInit"); + while (!renderer_inited) { + sleep_ms(20); + } } - if (renderer_inited) { - NativeUpdate(); + NativeUpdate(); - NativeRender(graphicsContext); - time_update(); - } else { - ELOG("BAD: Ended up in nativeRender even though app has quit.%s", ""); - // Shouldn't really get here. - } + NativeRender(graphicsContext); + time_update(); std::lock_guard guard(frameCommandLock); if (!nativeActivity) { @@ -498,6 +565,21 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, ProcessFrameCommands(env); } +extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { + static bool hasSetThreadName = false; + if (!hasSetThreadName) { + hasSetThreadName = true; + setCurrentThreadName("AndroidRender"); + } + + if (useCPUThread) { + // This is the "GPU thread". + graphicsContext->ThreadFrame(); + } else { + UpdateRunLoopAndroid(env); + } +} + void System_AskForPermission(SystemPermission permission) { switch (permission) { case SYSTEM_PERMISSION_STORAGE: @@ -762,6 +844,8 @@ static void ProcessFrameCommands(JNIEnv *env) { } extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(JNIEnv *env, jobject obj, jobject _surf) { + // Needed for Vulkan, even if we're not using the old EGL path. + exitRenderLoop = false; // This is up here to prevent race conditions, in case we pause during init. renderLoopRunning = true; @@ -787,14 +871,8 @@ retry: bool vulkan = g_Config.iGPUBackend == (int)GPUBackend::VULKAN; int tries = 0; - AndroidGraphicsContext *graphicsContext; - if (vulkan) { - graphicsContext = new AndroidVulkanContext(); - } else { - graphicsContext = new AndroidEGLGraphicsContext(); - } - if (!graphicsContext->Init(wnd, desiredBackbufferSizeX, desiredBackbufferSizeY, backbuffer_format, androidVersion)) { + if (!graphicsContext->InitFromRenderThread(wnd, desiredBackbufferSizeX, desiredBackbufferSizeY, backbuffer_format, androidVersion)) { ELOG("Failed to initialize graphics context."); if (!exitRenderLoop && (vulkan && tries < 2)) { diff --git a/android/src/org/ppsspp/ppsspp/NativeSurfaceView.java b/android/src/org/ppsspp/ppsspp/NativeSurfaceView.java index 2d53328573..1e13dba115 100644 --- a/android/src/org/ppsspp/ppsspp/NativeSurfaceView.java +++ b/android/src/org/ppsspp/ppsspp/NativeSurfaceView.java @@ -47,7 +47,7 @@ public class NativeSurfaceView extends SurfaceView implements SensorEventListene Log.i(TAG, "MOGA initialized"); mController.setListener(this, new Handler()); } catch (Exception e) { - Log.i(TAG, "Moga failed to initialize"); + // Ignore. } } From bd3a681fd3c05ce78a276f93800bf573d8c3b33c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 28 Jan 2018 17:27:23 +0100 Subject: [PATCH 091/291] Enough JNI/threading hackery to get it to run on Android! Broken readbacks make it crash alot though. --- android/jni/AndroidGraphicsContext.h | 2 +- android/jni/app-android.cpp | 76 ++++++++++++++---------- android/jni/app-android.h | 5 +- ext/native/gfx_es2/draw_text_android.cpp | 4 +- ext/native/thin3d/DataFormatGL.cpp | 2 +- 5 files changed, 52 insertions(+), 37 deletions(-) diff --git a/android/jni/AndroidGraphicsContext.h b/android/jni/AndroidGraphicsContext.h index 72279b7d6d..589cddc97d 100644 --- a/android/jni/AndroidGraphicsContext.h +++ b/android/jni/AndroidGraphicsContext.h @@ -21,5 +21,5 @@ class AndroidGraphicsContext : public GraphicsContext { public: // This is different than the base class function since on // Android (EGL, Vulkan) we do have all this info on the render thread. - virtual bool InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) {} + virtual bool InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) = 0; }; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 819d88468c..2d0731d711 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -51,10 +51,6 @@ #include "app-android.h" -JNIEnv *jniEnvMain; -JNIEnv *jniEnvGraphics; -JavaVM *javaVM; - bool useCPUThread = true; enum class EmuThreadState { @@ -113,6 +109,12 @@ static int backbuffer_format; // Android PixelFormat enum static int desiredBackbufferSizeX; static int desiredBackbufferSizeY; +// Cache the class loader so we can use it from native threads. Required for TextAndroid. +JavaVM* gJvm = nullptr; +static jobject gClassLoader; +static jmethodID gFindClassMethod; + + static jmethodID postCommand; static jobject nativeActivity; static volatile bool exitRenderLoop; @@ -132,9 +134,44 @@ static std::map permissions; AndroidGraphicsContext *graphicsContext; -static void EmuThreadFunc(JavaVM *vm) { +JNIEnv* getEnv() { JNIEnv *env; - vm->AttachCurrentThread(&env, nullptr); + int status = gJvm->GetEnv((void**)&env, JNI_VERSION_1_6); + if(status < 0) { + status = gJvm->AttachCurrentThread(&env, NULL); + if(status < 0) { + return nullptr; + } + } + return env; +} + +jclass findClass(const char* name) { + return static_cast(getEnv()->CallObjectMethod(gClassLoader, gFindClassMethod, getEnv()->NewStringUTF(name))); +} + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *pjvm, void *reserved) { + ILOG("JNI_OnLoad"); + gJvm = pjvm; // cache the JavaVM pointer + auto env = getEnv(); + //replace with one of your classes in the line below + auto randomClass = env->FindClass("org/ppsspp/ppsspp/NativeActivity"); + jclass classClass = env->GetObjectClass(randomClass); + auto classLoaderClass = env->FindClass("java/lang/ClassLoader"); + auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader", + "()Ljava/lang/ClassLoader;"); + gClassLoader = env->NewGlobalRef(env->CallObjectMethod(randomClass, getClassLoaderMethod)); + gFindClassMethod = env->GetMethodID(classLoaderClass, "findClass", + "(Ljava/lang/String;)Ljava/lang/Class;"); + return JNI_VERSION_1_6; +} + +static void EmuThreadFunc() { + JNIEnv *env; + gJvm->AttachCurrentThread(&env, nullptr); + + setCurrentThreadName("Emu"); + // There's no real requirement that NativeInit happen on this thread. // We just call the update/render loop here. emuThreadState = (int)EmuThreadState::RUNNING; @@ -142,14 +179,12 @@ static void EmuThreadFunc(JavaVM *vm) { UpdateRunLoopAndroid(env); } emuThreadState = (int)EmuThreadState::STOPPED; - vm->DetachCurrentThread(); + gJvm->DetachCurrentThread(); } static void EmuThreadStart(JNIEnv *env) { emuThreadState = (int)EmuThreadState::START_REQUESTED; - JavaVM *vm; - env->GetJavaVM(&vm); - emuThread = std::thread(&EmuThreadFunc, vm); + emuThread = std::thread(&EmuThreadFunc); } static void EmuThreadStop() { @@ -306,9 +341,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init (JNIEnv *env, jclass, jstring jmodel, jint jdeviceType, jstring jlangRegion, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jcacheDir, jstring jshortcutParam, jint jAndroidVersion, jstring jboard) { - jniEnvMain = env; - env->GetJavaVM(&javaVM); - setCurrentThreadName("androidInit"); // Makes sure we get early permission grants. @@ -472,15 +504,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { // JavaEGL extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, jobject obj) { - // Need to get the local JNI env for the graphics thread. Used later in draw_text_android. - int res = javaVM->GetEnv((void **)&jniEnvGraphics, JNI_VERSION_1_6); - if (res != JNI_OK) { - ELOG("GetEnv failed: %d", res); - } - - if (!graphicsContext) - Crash(); - // We should be running on the render thread here. std::string errorMessage; if (renderer_inited) { @@ -495,7 +518,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, ILOG("NativeApp.displayInit() first time"); graphicsContext->InitFromRenderThread(nullptr, 0, 0, 0, 0); graphicsContext->ThreadStart(); - NativeInitGraphics(graphicsContext); renderer_inited = true; } NativeMessageReceived("recreateviews", ""); @@ -548,6 +570,7 @@ void UpdateRunLoopAndroid(JNIEnv *env) { while (!renderer_inited) { sleep_ms(20); } + NativeInitGraphics(graphicsContext); } NativeUpdate(); @@ -852,12 +875,6 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(J ANativeWindow *wnd = ANativeWindow_fromSurface(env, _surf); - // Need to get the local JNI env for the graphics thread. Used later in draw_text_android. - int res = javaVM->GetEnv((void **)&jniEnvGraphics, JNI_VERSION_1_6); - if (res != JNI_OK) { - ELOG("GetEnv failed: %d", res); - } - WLOG("runEGLRenderLoop. display_xres=%d display_yres=%d", display_xres, display_yres); if (wnd == nullptr) { @@ -922,7 +939,6 @@ retry: graphicsContext = nullptr; renderLoopRunning = false; WLOG("Render loop function exited."); - jniEnvGraphics = nullptr; return true; } diff --git a/android/jni/app-android.h b/android/jni/app-android.h index 04a849b1bc..49d0dab435 100644 --- a/android/jni/app-android.h +++ b/android/jni/app-android.h @@ -6,8 +6,7 @@ #include -extern JNIEnv *jniEnvMain; -extern JNIEnv *jniEnvGraphics; -extern JavaVM *javaVM; +jclass findClass(const char* name); +JNIEnv* getEnv(); #endif diff --git a/ext/native/gfx_es2/draw_text_android.cpp b/ext/native/gfx_es2/draw_text_android.cpp index 68138ee9a4..1bc3bc6639 100644 --- a/ext/native/gfx_es2/draw_text_android.cpp +++ b/ext/native/gfx_es2/draw_text_android.cpp @@ -16,9 +16,9 @@ #include TextDrawerAndroid::TextDrawerAndroid(Draw::DrawContext *draw) : TextDrawer(draw) { - env_ = jniEnvGraphics; + env_ = getEnv(); const char *textRendererClassName = "org/ppsspp/ppsspp/TextRenderer"; - jclass localClass = env_->FindClass(textRendererClassName); + jclass localClass = findClass(textRendererClassName); cls_textRenderer = reinterpret_cast(env_->NewGlobalRef(localClass)); ILOG("cls_textRender: %p", cls_textRenderer); if (cls_textRenderer) { diff --git a/ext/native/thin3d/DataFormatGL.cpp b/ext/native/thin3d/DataFormatGL.cpp index 389d6046e8..e2aa7a7a1b 100644 --- a/ext/native/thin3d/DataFormatGL.cpp +++ b/ext/native/thin3d/DataFormatGL.cpp @@ -87,4 +87,4 @@ bool Thin3DFormatToFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuint return true; } -} \ No newline at end of file +} From 6c109abd9e77c85b0ba7c241ece8dacd8e228aa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 28 Jan 2018 18:00:48 +0100 Subject: [PATCH 092/291] Don't crash on missing readback formats. --- ext/native/thin3d/DataFormatGL.cpp | 1 - ext/native/thin3d/GLQueueRunner.cpp | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/native/thin3d/DataFormatGL.cpp b/ext/native/thin3d/DataFormatGL.cpp index e2aa7a7a1b..5d48f15868 100644 --- a/ext/native/thin3d/DataFormatGL.cpp +++ b/ext/native/thin3d/DataFormatGL.cpp @@ -81,7 +81,6 @@ bool Thin3DFormatToFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuint #endif default: - _assert_msg_(G3D, false, "Thin3d GL: Unsupported texture format %d", (int)fmt); return false; } return true; diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index a895ed4649..3ea3636968 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -984,7 +984,8 @@ void GLQueueRunner::PerformReadback(const GLRStep &pass) { GLuint type; int alignment; if (!Draw::Thin3DFormatToFormatAndType(pass.readback.dstFormat, internalFormat, format, type, alignment)) { - assert(false); + ELOG("Readback failed - format %d not available", (int)pass.readback.dstFormat); + return; } int pixelStride = pass.readback.srcRect.w; // Apply the correct alignment. From 19ab367591764b27ba585160d6f2c42ed6ce95f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 28 Jan 2018 19:26:42 +0100 Subject: [PATCH 093/291] Fix some accidental extra-indentation --- android/jni/AndroidEGLContext.cpp | 4 +--- android/jni/AndroidVulkanContext.cpp | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/android/jni/AndroidEGLContext.cpp b/android/jni/AndroidEGLContext.cpp index c9b5d81251..4bc86f1a9e 100644 --- a/android/jni/AndroidEGLContext.cpp +++ b/android/jni/AndroidEGLContext.cpp @@ -6,9 +6,7 @@ #include "GL/GLInterface/EGLAndroid.h" #include "Core/System.h" -bool AndroidEGLGraphicsContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, - int desiredBackbufferSizeY, - int backbufferFormat, int androidVersion) { +bool AndroidEGLGraphicsContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) { ILOG("AndroidEGLGraphicsContext::Init()"); wnd_ = wnd; gl = HostGL_CreateGLInterface(); diff --git a/android/jni/AndroidVulkanContext.cpp b/android/jni/AndroidVulkanContext.cpp index 29ad3f3103..18463411c2 100644 --- a/android/jni/AndroidVulkanContext.cpp +++ b/android/jni/AndroidVulkanContext.cpp @@ -74,9 +74,7 @@ AndroidVulkanContext::~AndroidVulkanContext() { g_Vulkan = nullptr; } -bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, - int desiredBackbufferSizeY, int backbufferFormat, - int androidVersion) { +bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) { ILOG("AndroidVulkanContext::Init"); init_glslang(); From bd2c875c9a7d73a930acac3bf9bc04568990ab45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 28 Jan 2018 21:28:16 +0100 Subject: [PATCH 094/291] Fix readback color conversion --- ext/native/thin3d/GLQueueRunner.cpp | 48 +++++++++++++++++++---------- ext/native/thin3d/GLQueueRunner.h | 3 ++ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 3ea3636968..333ebd6d74 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -41,7 +41,7 @@ void GLQueueRunner::CreateDeviceObjects() { populate(GL_RENDERER); populate(GL_VERSION); populate(GL_SHADING_LANGUAGE_VERSION); - populate(GL_EXTENSIONS); + populate(GL_EXTENSIONS); // TODO: Not OK to query this in core profile! } void GLQueueRunner::DestroyDeviceObjects() { @@ -52,6 +52,10 @@ void GLQueueRunner::DestroyDeviceObjects() { if (gl_extensions.ARB_vertex_array_object) { glDeleteVertexArrays(1, &globalVAO_); } + delete[] readbackBuffer_; + readbackBufferSize_ = 0; + delete[] tempBuffer_; + tempBufferSize_ = 0; } void GLQueueRunner::RunInitSteps(const std::vector &steps) { @@ -969,6 +973,8 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) { } void GLQueueRunner::PerformReadback(const GLRStep &pass) { + using namespace Draw; + GLRFramebuffer *fb = pass.readback.src; fbo_bind_fb_target(true, fb ? fb->handle : 0); @@ -979,17 +985,16 @@ void GLQueueRunner::PerformReadback(const GLRStep &pass) { CHECK_GL_ERROR_IF_DEBUG(); - GLuint internalFormat; - GLuint format; - GLuint type; - int alignment; - if (!Draw::Thin3DFormatToFormatAndType(pass.readback.dstFormat, internalFormat, format, type, alignment)) { - ELOG("Readback failed - format %d not available", (int)pass.readback.dstFormat); - return; - } + // Always read back in 8888 format. + const GLuint internalFormat = GL_RGBA; + const GLuint format = GL_RGBA; + const GLuint type = GL_UNSIGNED_BYTE; + const int srcAlignment = 4; + int dstAlignment = DataFormatSizeInBytes(pass.readback.dstFormat); + int pixelStride = pass.readback.srcRect.w; // Apply the correct alignment. - glPixelStorei(GL_PACK_ALIGNMENT, alignment); + glPixelStorei(GL_PACK_ALIGNMENT, srcAlignment); if (!gl_extensions.IsGLES || gl_extensions.GLES3) { // Some drivers seem to require we specify this. See #8254. glPixelStorei(GL_PACK_ROW_LENGTH, pixelStride); @@ -997,21 +1002,32 @@ void GLQueueRunner::PerformReadback(const GLRStep &pass) { GLRect2D rect = pass.readback.srcRect; - int size = alignment * rect.w * rect.h; - if (size > readbackBufferSize_) { + bool convert = pass.readback.dstFormat != DataFormat::R8G8B8A8_UNORM; + + int tempSize = srcAlignment * rect.w * rect.h; + int readbackSize = dstAlignment * rect.w * rect.h; + if (convert && tempSize > tempBufferSize_) { + delete[] tempBuffer_; + tempBuffer_ = new uint8_t[tempSize]; + tempBufferSize_ = tempSize; + } + if (readbackSize > readbackBufferSize_) { delete[] readbackBuffer_; - readbackBuffer_ = new uint8_t[size]; - readbackBufferSize_ = size; + readbackBuffer_ = new uint8_t[readbackSize]; + readbackBufferSize_ = readbackSize; } - glReadPixels(rect.x, rect.y, rect.w, rect.h, format, type, readbackBuffer_); - + glReadPixels(rect.x, rect.y, rect.w, rect.h, format, type, convert ? tempBuffer_ : readbackBuffer_); #ifdef DEBUG_READ_PIXELS LogReadPixelsError(glGetError()); #endif if (!gl_extensions.IsGLES || gl_extensions.GLES3) { glPixelStorei(GL_PACK_ROW_LENGTH, 0); } + if (convert) { + ConvertFromRGBA8888(readbackBuffer_, tempBuffer_, pixelStride, pixelStride, rect.w, rect.h, pass.readback.dstFormat); + } + CHECK_GL_ERROR_IF_DEBUG(); } diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 511e3425a1..c5ff40c832 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -375,6 +375,9 @@ private: // We size it generously. uint8_t *readbackBuffer_ = nullptr; int readbackBufferSize_ = 0; + // Temp buffer for color conversion + uint8_t *tempBuffer_ = nullptr; + int tempBufferSize_ = 0; float maxAnisotropyLevel_ = 0.0f; From 26b146a247af93d0a99eaa5703776bd9fe74f928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 30 Jan 2018 12:28:44 +0100 Subject: [PATCH 095/291] Buildfixes --- android/jni/AndroidEGLContext.cpp | 1 + android/jni/AndroidJavaGLContext.cpp | 2 ++ android/jni/AndroidVulkanContext.cpp | 2 ++ 3 files changed, 5 insertions(+) diff --git a/android/jni/AndroidEGLContext.cpp b/android/jni/AndroidEGLContext.cpp index 8742085535..117c431d80 100644 --- a/android/jni/AndroidEGLContext.cpp +++ b/android/jni/AndroidEGLContext.cpp @@ -1,3 +1,4 @@ +#include #include "base/logging.h" #include "base/NativeApp.h" #include "gfx_es2/gpu_features.h" diff --git a/android/jni/AndroidJavaGLContext.cpp b/android/jni/AndroidJavaGLContext.cpp index 8a97a62187..751f9d7539 100644 --- a/android/jni/AndroidJavaGLContext.cpp +++ b/android/jni/AndroidJavaGLContext.cpp @@ -1,3 +1,5 @@ +#include + #include "AndroidJavaGLContext.h" #include "base/NativeApp.h" #include "gfx_es2/gpu_features.h" diff --git a/android/jni/AndroidVulkanContext.cpp b/android/jni/AndroidVulkanContext.cpp index 99b21469be..04373c874d 100644 --- a/android/jni/AndroidVulkanContext.cpp +++ b/android/jni/AndroidVulkanContext.cpp @@ -1,3 +1,5 @@ +#include + #include "AndroidVulkanContext.h" #include "base/NativeApp.h" #include "base/display.h" From 56eb2b892f00c142453f5d8b30dc8e16a6f3dea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 30 Jan 2018 19:39:53 +0100 Subject: [PATCH 096/291] Minor: Make the Vulkan allocator debug visualizer slightly better looking by adding a border. --- GPU/GPU.vcxproj.filters | 8 ++++++-- GPU/Vulkan/DebugVisVulkan.cpp | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index ddc5b0ff12..7dc2f25cad 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -270,7 +270,9 @@ D3D11 - + + Vulkan + @@ -537,6 +539,8 @@ Common - + + Vulkan + \ No newline at end of file diff --git a/GPU/Vulkan/DebugVisVulkan.cpp b/GPU/Vulkan/DebugVisVulkan.cpp index cc62294d4a..7bfc54bdeb 100644 --- a/GPU/Vulkan/DebugVisVulkan.cpp +++ b/GPU/Vulkan/DebugVisVulkan.cpp @@ -81,6 +81,8 @@ void DrawAllocatorVis(UIContext *ui, GPUInterface *gpu) { UI::Drawable white(0xFFFFFFFF); draw->BindTexture(0, tex); + // Cheap black border. + ui->Draw()->Rect(x-2, y-2, w+4, h+4, 0xE0000000); ui->Draw()->Rect(x, y, w, h, 0xFFFFFFFF); ui->Flush(); texturesToDelete.push_back(tex); From 3a988400a702ede4137ee3f6d885796c03d727ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 30 Jan 2018 13:32:10 +0100 Subject: [PATCH 097/291] Simpler way to deal with the GL deleter --- ext/native/thin3d/GLQueueRunner.cpp | 47 +++++++++++++++++++++++++-- ext/native/thin3d/GLQueueRunner.h | 2 -- ext/native/thin3d/GLRenderManager.cpp | 13 +++----- ext/native/thin3d/GLRenderManager.h | 21 ++++++------ 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 333ebd6d74..9fd394c8be 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -424,9 +424,52 @@ void GLQueueRunner::RunSteps(const std::vector &steps) { } void GLQueueRunner::LogSteps(const std::vector &steps) { - + for (int i = 0; i < steps.size(); i++) { + const GLRStep &step = *steps[i]; + switch (step.stepType) { + case GLRStepType::RENDER: + LogRenderPass(step); + break; + case GLRStepType::COPY: + LogCopy(step); + break; + case GLRStepType::BLIT: + LogBlit(step); + break; + case GLRStepType::READBACK: + LogReadback(step); + break; + case GLRStepType::READBACK_IMAGE: + LogReadbackImage(step); + break; + default: + Crash(); + break; + } + delete steps[i]; + } } +// TODO: Improve these. +void GLQueueRunner::LogRenderPass(const GLRStep &pass) { + ILOG("RenderPass (%d commands)", (int)pass.commands.size()); +} + +void GLQueueRunner::LogCopy(const GLRStep &pass) { + ILOG("Copy"); +} + +void GLQueueRunner::LogBlit(const GLRStep &pass) { + ILOG("Blit"); +} + +void GLQueueRunner::LogReadback(const GLRStep &pass) { + ILOG("Readback"); +} + +void GLQueueRunner::LogReadbackImage(const GLRStep &pass) { + ILOG("ReadbackImage"); +} void GLQueueRunner::PerformBlit(const GLRStep &step) { // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing @@ -990,7 +1033,7 @@ void GLQueueRunner::PerformReadback(const GLRStep &pass) { const GLuint format = GL_RGBA; const GLuint type = GL_UNSIGNED_BYTE; const int srcAlignment = 4; - int dstAlignment = DataFormatSizeInBytes(pass.readback.dstFormat); + int dstAlignment = (int)DataFormatSizeInBytes(pass.readback.dstFormat); int pixelStride = pass.readback.srcRect.w; // Apply the correct alignment. diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index c5ff40c832..8d50e0ca44 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -355,8 +355,6 @@ private: void LogReadback(const GLRStep &pass); void LogReadbackImage(const GLRStep &pass); - void ResizeReadbackBuffer(size_t requiredSize); - void fbo_ext_create(const GLRInitStep &step); void fbo_bind_fb_target(bool read, GLuint name); GLenum fbo_get_fb_target(bool read, GLuint **cached); diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 2792e76d1a..abd267aee1 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -13,7 +13,6 @@ #endif void GLDeleter::Perform() { - deleterMutex_.lock(); for (auto shader : shaders) { delete shader; } @@ -38,7 +37,6 @@ void GLDeleter::Perform() { delete framebuffer; } framebuffers.clear(); - deleterMutex_.unlock(); } GLRenderManager::GLRenderManager() { @@ -357,8 +355,6 @@ void GLRenderManager::Finish() { frameData.pull_condVar.notify_all(); } - frameData_[curFrame_].deleter.Take(deleter_); - curFrame_++; if (curFrame_ >= MAX_INFLIGHT_FRAMES) curFrame_ = 0; @@ -380,10 +376,6 @@ void GLRenderManager::Submit(int frame, bool triggerFence) { // When !triggerFence, we notify after syncing with Vulkan. - // Putting deletes here is safe but only because OpenGL has its own delete handling.. - // ideally we'd like to wait a frame or two. - frameData.deleter.Perform(); - if (useThread_ && triggerFence) { VLOG("PULL: Frame %d.readyForFence = true", frame); @@ -414,6 +406,10 @@ void GLRenderManager::Run(int frame) { BeginSubmitFrame(frame); FrameData &frameData = frameData_[frame]; + + // Delete stuff from the last round. + frameData.deleter_prev.Perform(); + auto &stepsOnThread = frameData_[frame].steps; auto &initStepsOnThread = frameData_[frame].initSteps; // queueRunner_.LogSteps(stepsOnThread); @@ -424,6 +420,7 @@ void GLRenderManager::Run(int frame) { switch (frameData.type) { case GLRRunType::END: + frameData.deleter_prev.Take(frameData.deleter); EndSubmitFrame(frame); break; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 6bd2d7caf1..239ff0f3c0 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -148,12 +148,12 @@ enum class GLRRunType { SYNC, }; +// Synchronize this externally if needed, no mutex anymore. class GLDeleter { public: void Perform(); void Take(GLDeleter &other) { - deleterMutex_.lock(); _assert_msg_(G3D, shaders.empty() && programs.empty() && buffers.empty() && textures.empty() && inputLayouts.empty() && framebuffers.empty(), "Deleter already has stuff"); shaders = std::move(other.shaders); programs = std::move(other.programs); @@ -167,7 +167,6 @@ public: other.textures.clear(); other.inputLayouts.clear(); other.framebuffers.clear(); - deleterMutex_.unlock(); } std::vector shaders; @@ -176,7 +175,6 @@ public: std::vector textures; std::vector inputLayouts; std::vector framebuffers; - std::mutex deleterMutex_; }; class GLRInputLayout { @@ -291,22 +289,22 @@ public: } void DeleteShader(GLRShader *shader) { - deleter_.shaders.push_back(shader); + frameData_[curFrame_].deleter.shaders.push_back(shader); } void DeleteProgram(GLRProgram *program) { - deleter_.programs.push_back(program); + frameData_[curFrame_].deleter.programs.push_back(program); } void DeleteBuffer(GLRBuffer *buffer) { - deleter_.buffers.push_back(buffer); + frameData_[curFrame_].deleter.buffers.push_back(buffer); } void DeleteTexture(GLRTexture *texture) { - deleter_.textures.push_back(texture); + frameData_[curFrame_].deleter.textures.push_back(texture); } void DeleteInputLayout(GLRInputLayout *inputLayout) { - deleter_.inputLayouts.push_back(inputLayout); + frameData_[curFrame_].deleter.inputLayouts.push_back(inputLayout); } void DeleteFramebuffer(GLRFramebuffer *framebuffer) { - deleter_.framebuffers.push_back(framebuffer); + frameData_[curFrame_].deleter.framebuffers.push_back(framebuffer); } void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, GLRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil); @@ -696,7 +694,10 @@ private: bool hasBegun = false; uint32_t curSwapchainImage = -1; + std::mutex deleter_mutex; GLDeleter deleter; + GLDeleter deleter_prev; + std::set activePushBuffers; }; @@ -721,8 +722,6 @@ private: bool nextFrame = false; bool firstFrame = true; - GLDeleter deleter_; - bool useThread_ = true; int curFrame_ = 0; From 98cfaef6ec2a62e6b0cb97b67a0d51b99dd67e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Jan 2018 12:05:18 +0100 Subject: [PATCH 098/291] Rough fix for threaded GL for Qt. --- Qt/QtMain.cpp | 97 ++++++++++++++++++++++++++++++++++++++++----------- Qt/QtMain.h | 43 +++++++++++++++++++++-- 2 files changed, 117 insertions(+), 23 deletions(-) diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 3030f64354..ea364b08a5 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -29,6 +29,7 @@ #include "QtMain.h" #include "gfx_es2/gpu_features.h" #include "math/math_util.h" +#include "thread/threadutil.h" #include @@ -188,31 +189,64 @@ static int mainInternal(QApplication &a) return a.exec(); } +void MainUI::EmuThreadFunc() { + ILOG("In emu thread"); + setCurrentThreadName("Emu"); + + // There's no real requirement that NativeInit happen on this thread. + // We just call the update/render loop here. + emuThreadState = (int)EmuThreadState::RUNNING; + while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) { + #ifdef SDL + SDL_PumpEvents(); + #endif + updateAccelerometer(); + time_update(); + UpdateRunLoop(); + } + emuThreadState = (int)EmuThreadState::STOPPED; +} + +void MainUI::EmuThreadStart() { + emuThreadState = (int)EmuThreadState::START_REQUESTED; + emuThread = std::thread([&]() { this->EmuThreadFunc(); } ); +} + +void MainUI::EmuThreadStop() { + emuThreadState = (int)EmuThreadState::QUIT_REQUESTED; + emuThread.join(); + emuThread = std::thread(); +} + MainUI::MainUI(QWidget *parent): - QGLWidget(parent) + QGLWidget(parent) { - setAttribute(Qt::WA_AcceptTouchEvents); + emuThreadState = (int)EmuThreadState::DISABLED; + setAttribute(Qt::WA_AcceptTouchEvents); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) - setAttribute(Qt::WA_LockLandscapeOrientation); + setAttribute(Qt::WA_LockLandscapeOrientation); #endif #if defined(MOBILE_DEVICE) - acc = new QAccelerometer(this); - acc->start(); + acc = new QAccelerometer(this); + acc->start(); #endif - setFocus(); - setFocusPolicy(Qt::StrongFocus); - startTimer(16); + setFocus(); + setFocusPolicy(Qt::StrongFocus); + startTimer(16); } MainUI::~MainUI() { + if (useThread_) { + EmuThreadStop(); + } #if defined(MOBILE_DEVICE) - delete acc; + delete acc; #endif - NativeShutdownGraphics(); - graphicsContext->Shutdown(); - delete graphicsContext; - graphicsContext = nullptr; + NativeShutdownGraphics(); + graphicsContext->Shutdown(); + delete graphicsContext; + graphicsContext = nullptr; } QString MainUI::InputBoxGetQString(QString title, QString defaultValue) @@ -330,18 +364,36 @@ void MainUI::initializeGL() if (gl_extensions.IsCoreContext) glGetError(); #endif + ILOG("Initializing graphics context"); graphicsContext = new QtDummyGraphicsContext(); NativeInitGraphics(graphicsContext); + + // OpenGL uses a background thread to do the main processing and only renders on the gl thread. + useThread_ = g_Config.iGPUBackend == (int)GPUBackend::OPENGL; + + if (useThread_) { + ILOG("Using thread, starting emu thread"); + EmuThreadStart(); + + graphicsContext->ThreadStart(); + } else { + ILOG("Not using thread, backend=%d", (int)g_Config.iGPUBackend); + } } void MainUI::paintGL() { -#ifdef SDL - SDL_PumpEvents(); -#endif - updateAccelerometer(); - time_update(); - UpdateRunLoop(); + if (useThread_) { + graphicsContext->ThreadFrame(); + // Do the rest in EmuThreadFunc + } else { + #ifdef SDL + SDL_PumpEvents(); + #endif + updateAccelerometer(); + time_update(); + UpdateRunLoop(); + } } void MainUI::updateAccelerometer() @@ -454,14 +506,17 @@ int main(int argc, char *argv[]) #endif savegame_dir += "/"; external_dir += "/"; - + bool fullscreenCLI=false; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) fullscreenCLI=true; } NativeInit(argc, (const char **)argv, savegame_dir.c_str(), external_dir.c_str(), nullptr, fullscreenCLI); - + + // TODO: Support other backends than GL, like Vulkan, in the Qt backend. + g_Config.iGPUBackend = (int)GPUBackend::OPENGL; + int ret = mainInternal(a); NativeShutdownGraphics(); diff --git a/Qt/QtMain.h b/Qt/QtMain.h index f4f1b3c5c2..8f0538f7c6 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -19,6 +19,8 @@ QTM_USE_NAMESPACE #endif #include +#include +#include #include "base/display.h" #include "base/logging.h" @@ -37,6 +39,7 @@ QTM_USE_NAMESPACE #include "Core/Core.h" #include "Core/Config.h" #include "Core/System.h" +#include "thin3d/GLRenderManager.h" // Input void SimulateGamepad(); @@ -47,21 +50,48 @@ public: CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); SetGPUBackend(GPUBackend::OPENGL); + renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); bool success = draw_->CreatePresets(); assert(success); } + ~QtDummyGraphicsContext() { delete draw_; + draw_ = nullptr; + renderManager_ = nullptr; } Draw::DrawContext *GetDrawContext() override { return draw_; } + + void ThreadStart() override { + renderManager_->ThreadStart(); + } + + bool ThreadFrame() override { + return renderManager_->ThreadFrame(); + } + + void ThreadEnd() override { + renderManager_->ThreadEnd(); + } + private: - Draw::DrawContext *draw_; + Draw::DrawContext *draw_ = nullptr; + GLRenderManager *renderManager_ = nullptr; }; -//GUI +enum class EmuThreadState { + DISABLED, + START_REQUESTED, + RUNNING, + QUIT_REQUESTED, + STOPPED, +}; + + +// GUI, thread manager class MainUI : public QGLWidget { Q_OBJECT @@ -87,6 +117,10 @@ protected: void updateAccelerometer(); + void EmuThreadFunc(); + void EmuThreadStart(); + void EmuThreadStop(); + private: QtDummyGraphicsContext *graphicsContext; @@ -94,6 +128,11 @@ private: #if defined(MOBILE_DEVICE) QAccelerometer* acc; #endif + + std::thread emuThread; + std::atomic emuThreadState; + + bool useThread_ = false; }; extern MainUI* emugl; From 67b8c4527d3ea4b1a9e664757ba410a105de42f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Jan 2018 14:22:38 +0100 Subject: [PATCH 099/291] b.sh: Add a build option for address sanitizer. When enabled, we turn on some compatibility options to make it work right. --- CMakeLists.txt | 8 ++++++++ Common/MemArenaPosix.cpp | 2 +- Core/MemMap.h | 4 ++-- b.sh | 3 +++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7cbe623fb3..95db991510 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,7 @@ option(SIMULATOR "Set to ON when targeting an x86 simulator of an ARM platform" option(USE_FFMPEG "Build with FFMPEG support" ${USE_FFMPEG}) option(USE_SYSTEM_FFMPEG "Dynamically link against system FFMPEG" ${USE_SYSTEM_FFMPEG}) option(USE_WAYLAND_WSI "Set to ON to require Wayland support for Vulkan" ${USE_WAYLAND_WSI}) +option(USE_ADDRESS_SANITIZER "Use Clang memory sanitizer" ${USE_ADDRESS_SANITIZER}) if(UNIX AND NOT (APPLE OR ANDROID) AND VULKAN) add_definitions(-DVK_USE_PLATFORM_XLIB_KHR) @@ -214,6 +215,13 @@ if(NOT MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-switch -Wno-uninitialized") endif() + if(USE_ADDRESS_SANITIZER) + message("Address sanitizer enabled (DEBUG only)") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -fsanitize=address") + set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fsanitize=address") + add_definitions(-DUSE_ADDRESS_SANITIZER) + endif() + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -D_DEBUG") set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -Os -D_NDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -D_NDEBUG") diff --git a/Common/MemArenaPosix.cpp b/Common/MemArenaPosix.cpp index 18151d0b34..d550d5aaab 100644 --- a/Common/MemArenaPosix.cpp +++ b/Common/MemArenaPosix.cpp @@ -102,7 +102,7 @@ void MemArena::ReleaseView(void* view, size_t size) { u8* MemArena::Find4GBBase() { // Now, create views in high memory where there's plenty of space. -#if PPSSPP_ARCH(64BIT) +#if PPSSPP_ARCH(64BIT) && !defined(USE_ADDRESS_SANITIZER) // Very precarious - mmap cannot return an error when trying to map already used pages. // This makes the Windows approach above unusable on Linux, so we will simply pray... return reinterpret_cast(0x2300000000ULL); diff --git a/Core/MemMap.h b/Core/MemMap.h index a681df9d11..5c41f1e683 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -83,8 +83,8 @@ extern u32 g_MemorySize; extern u32 g_PSPModel; // UWP has such limited memory management that we need to mask -// even in 64-bit mode. -#if PPSSPP_ARCH(32BIT) || PPSSPP_PLATFORM(UWP) +// even in 64-bit mode. Also, when using the sanitizer, we need to mask as well. +#if PPSSPP_ARCH(32BIT) || PPSSPP_PLATFORM(UWP) || USE_ADDRESS_SANITIZER #define MASKED_PSP_MEMORY #endif diff --git a/b.sh b/b.sh index c0cc2115ab..f074ff0952 100755 --- a/b.sh +++ b/b.sh @@ -43,6 +43,9 @@ do export CC=/usr/bin/clang export CXX=/usr/bin/clang++ ;; + --sanitize) echo "Enabling address-sanitizer if available" + CMAKE_ARGS="-DUSE_ADDRESS_SANITIZER=ON ${CMAKE_ARGS}" + ;; *) MAKE_OPT="$1 ${MAKE_OPT}" ;; esac From 5351c9ddb3401d9fcd12816b22b882e29ec8e021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Jan 2018 17:07:20 +0100 Subject: [PATCH 100/291] gl-render-manager: Support scissored clears, as used by the GL backend. Fixes GT. --- GPU/GLES/DrawEngineGLES.cpp | 6 +++--- GPU/GLES/StencilBufferGLES.cpp | 4 ++-- ext/native/thin3d/GLQueueRunner.cpp | 11 +++++++++-- ext/native/thin3d/GLQueueRunner.h | 10 +++++++--- ext/native/thin3d/GLRenderManager.cpp | 5 ++++- ext/native/thin3d/GLRenderManager.h | 8 +++++++- ext/native/thin3d/thin3d_gl.cpp | 2 +- 7 files changed, 33 insertions(+), 13 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 77717aea19..247549dddf 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -724,13 +724,13 @@ rotateVBO: if (alphaMask) target |= GL_STENCIL_BUFFER_BIT; if (depthMask) target |= GL_DEPTH_BUFFER_BIT; - render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask); - framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); - int scissorX1 = gstate.getScissorX1(); int scissorY1 = gstate.getScissorY1(); int scissorX2 = gstate.getScissorX2() + 1; int scissorY2 = gstate.getScissorY2() + 1; + + render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask, scissorX1, scissorY1, scissorX2 - scissorX1, scissorY2 - scissorY1); + framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); framebufferManager_->SetSafeSize(scissorX2, scissorY2); if (g_Config.bBlockTransferGPU && (gstate_c.featureFlags & GPU_USE_CLEAR_RAM_HACK) && colorMask && (alphaMask || gstate.FrameBufFormat() == GE_FORMAT_565)) { diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index e86aad078f..093694dddd 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -113,7 +113,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe if (dstBuffer->fbo) { draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }); } - render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT, 0x8); + render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT, 0x8, 0, 0, 0, 0); gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE); return true; } @@ -169,7 +169,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe textureCacheGL_->ForgetLastTexture(); // We must bind the program after starting the render pass, and set the color mask after clearing. - render_->Clear(0, 0, 0, GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 0x8); + render_->Clear(0, 0, 0, GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 0x8, 0, 0, 0, 0); render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF); render_->BindProgram(stencilUploadProgram_); render_->SetNoBlendAndMask(0x8); diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 9fd394c8be..09a45ab873 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -629,7 +629,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { #endif break; case GLRRenderCommand::CLEAR: - glDisable(GL_SCISSOR_TEST); + if (c.clear.scissorW > 0) { + glEnable(GL_SCISSOR_TEST); + glScissor(c.clear.scissorX, c.clear.scissorY, c.clear.scissorW, c.clear.scissorH); + } else { + glDisable(GL_SCISSOR_TEST); + } if (c.clear.colorMask != colorMask) { glColorMask(c.clear.colorMask & 1, (c.clear.colorMask >> 1) & 1, (c.clear.colorMask >> 2) & 1, (c.clear.colorMask >> 3) & 1); colorMask = c.clear.colorMask; @@ -650,7 +655,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glClearStencil(c.clear.clearStencil); } glClear(c.clear.clearMask); - glEnable(GL_SCISSOR_TEST); + if (c.clear.scissorW > 0) { + glDisable(GL_SCISSOR_TEST); + } break; case GLRRenderCommand::INVALIDATE: { diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 8d50e0ca44..33e979d585 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -122,9 +122,13 @@ struct GLRRenderData { struct { uint32_t clearColor; float clearZ; - int clearStencil; - int clearMask; // VK_IMAGE_ASPECT_COLOR_BIT etc - int colorMask; // Like blend, but for the clear. + uint8_t clearStencil; + uint8_t colorMask; // Like blend, but for the clear. + GLuint clearMask; // GL_COLOR_BUFFER_BIT etc + int16_t scissorX; + int16_t scissorY; + int16_t scissorW; + int16_t scissorH; } clear; struct { int slot; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index abd267aee1..4e21eaf124 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -203,11 +203,14 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende data.clear.clearStencil = clearStencil; } if (clearMask) { + data.clear.scissorX = 0; + data.clear.scissorY = 0; + data.clear.scissorW = 0; + data.clear.scissorH = 0; data.clear.clearMask = clearMask; data.clear.colorMask = 0xF; step->commands.push_back(data); } - curRenderStep_ = step; // Every step clears this state. diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 239ff0f3c0..b0b3b77f6c 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -578,14 +578,20 @@ public: curRenderStep_->commands.push_back(data); } - void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask, int colorMask = 0xF) { + // If scissorW == 0, no scissor is applied. + void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask, int colorMask, int scissorX, int scissorY, int scissorW, int scissorH) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::CLEAR }; + _assert_(clearMask != 0); // What would be the point? data.clear.clearMask = clearMask; data.clear.clearColor = clearColor; data.clear.clearZ = clearZ; data.clear.clearStencil = clearStencil; data.clear.colorMask = colorMask; + data.clear.scissorX = scissorX; + data.clear.scissorY = scissorY; + data.clear.scissorW = scissorW; + data.clear.scissorH = scissorH; curRenderStep_->commands.push_back(data); } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index b831e199a0..55691e84b9 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -1023,7 +1023,7 @@ void OpenGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stenc if (mask & FBChannel::FB_STENCIL_BIT) { glMask |= GL_STENCIL_BUFFER_BIT; } - renderManager_.Clear(colorval, depthVal, stencilVal, glMask); + renderManager_.Clear(colorval, depthVal, stencilVal, glMask, 0xF, 0, 0, targetWidth_, targetHeight_); } DrawContext *T3DCreateGLContext() { From 982a1710ae3c071e20b211e28a00aa2ceb41be6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Jan 2018 17:23:24 +0100 Subject: [PATCH 101/291] gl-render-manager: Fix postprocessing shaders. Fixes #10566. Live switching is broken though for some reason. --- GPU/Common/FramebufferCommon.cpp | 3 --- GPU/GLES/FramebufferManagerGLES.cpp | 9 +++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 3f93329d22..1447ca62ff 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -208,9 +208,6 @@ void FramebufferManagerCommon::SetNumExtraFBOs(int num) { extraFBOs_.push_back(fbo); } currentRenderVfb_ = 0; - // TODO: Should probably not do this bind. - if (num != 0) - draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } // Heuristics to figure out the size of FBO to create. diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 42015c1169..9754e2a185 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -154,7 +154,7 @@ void FramebufferManagerGLES::CompilePostShader() { std::vector shaders; shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vshader, "postshader")); - shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, fshader, "postshader")); + shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fshader, "postshader")); std::vector queries; queries.push_back({ &u_postShaderTex, "tex" }); queries.push_back({ &deltaLoc_, "u_texelDelta" }); @@ -164,9 +164,10 @@ void FramebufferManagerGLES::CompilePostShader() { std::vector inits; inits.push_back({ &u_postShaderTex, 0, 0 }); - postShaderProgram_ = render_->CreateProgram(shaders, {}, queries, inits, false); - render_->SetUniformI1(&u_postShaderTex, 0); - + std::vector semantics; + semantics.push_back({ 0, "a_position" }); + semantics.push_back({ 1, "a_texcoord0" }); + postShaderProgram_ = render_->CreateProgram(shaders, semantics, queries, inits, false); for (auto iter : shaders) { render_->DeleteShader(iter); } From c21b02a22dcf9b88c4e89c064f771983b1409a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Jan 2018 19:36:32 +0100 Subject: [PATCH 102/291] gl-render-manager: Use properly scaled scissor rectangle, oops. Fixes higher resolutions. --- GPU/GLES/DrawEngineGLES.cpp | 2 +- GPU/GLES/DrawEngineGLES.h | 3 +++ GPU/GLES/StateMappingGLES.cpp | 1 - 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 247549dddf..405b929e63 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -729,7 +729,7 @@ rotateVBO: int scissorX2 = gstate.getScissorX2() + 1; int scissorY2 = gstate.getScissorY2() + 1; - render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask, scissorX1, scissorY1, scissorX2 - scissorX1, scissorY2 - scissorY1); + render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask, vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH); framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); framebufferManager_->SetSafeSize(scissorX2, scissorY2); diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 7fa9f1e816..59246fb5cd 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -196,6 +196,9 @@ private: FragmentTestCacheGLES *fragmentTestCache_ = nullptr; Draw::DrawContext *draw_; + // Need to preserve the scissor for use when clearing. + ViewportAndScissor vpAndScissor; + int bufferDecimationCounter_ = 0; // Hardware tessellation diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index caa6ad2472..b3c25e01c2 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -301,7 +301,6 @@ void DrawEngineGLES::ApplyDrawState(int prim) { if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) { gstate_c.Clean(DIRTY_VIEWPORTSCISSOR_STATE); - ViewportAndScissor vpAndScissor; ConvertViewportAndScissor(useBufferedRendering, framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), From d6e888a39b11436aabb552a117d099b2a3781bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 4 Feb 2018 13:09:51 +0100 Subject: [PATCH 103/291] Revert "Simpler way to deal with the GL deleter" This reverts commit 3a988400a702ede4137ee3f6d885796c03d727ea. --- ext/native/thin3d/GLQueueRunner.cpp | 47 ++------------------------- ext/native/thin3d/GLQueueRunner.h | 2 ++ ext/native/thin3d/GLRenderManager.cpp | 13 +++++--- ext/native/thin3d/GLRenderManager.h | 21 ++++++------ 4 files changed, 23 insertions(+), 60 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 09a45ab873..96dfe71302 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -424,52 +424,9 @@ void GLQueueRunner::RunSteps(const std::vector &steps) { } void GLQueueRunner::LogSteps(const std::vector &steps) { - for (int i = 0; i < steps.size(); i++) { - const GLRStep &step = *steps[i]; - switch (step.stepType) { - case GLRStepType::RENDER: - LogRenderPass(step); - break; - case GLRStepType::COPY: - LogCopy(step); - break; - case GLRStepType::BLIT: - LogBlit(step); - break; - case GLRStepType::READBACK: - LogReadback(step); - break; - case GLRStepType::READBACK_IMAGE: - LogReadbackImage(step); - break; - default: - Crash(); - break; - } - delete steps[i]; - } + } -// TODO: Improve these. -void GLQueueRunner::LogRenderPass(const GLRStep &pass) { - ILOG("RenderPass (%d commands)", (int)pass.commands.size()); -} - -void GLQueueRunner::LogCopy(const GLRStep &pass) { - ILOG("Copy"); -} - -void GLQueueRunner::LogBlit(const GLRStep &pass) { - ILOG("Blit"); -} - -void GLQueueRunner::LogReadback(const GLRStep &pass) { - ILOG("Readback"); -} - -void GLQueueRunner::LogReadbackImage(const GLRStep &pass) { - ILOG("ReadbackImage"); -} void GLQueueRunner::PerformBlit(const GLRStep &step) { // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing @@ -1040,7 +997,7 @@ void GLQueueRunner::PerformReadback(const GLRStep &pass) { const GLuint format = GL_RGBA; const GLuint type = GL_UNSIGNED_BYTE; const int srcAlignment = 4; - int dstAlignment = (int)DataFormatSizeInBytes(pass.readback.dstFormat); + int dstAlignment = DataFormatSizeInBytes(pass.readback.dstFormat); int pixelStride = pass.readback.srcRect.w; // Apply the correct alignment. diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 33e979d585..6043e80c94 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -359,6 +359,8 @@ private: void LogReadback(const GLRStep &pass); void LogReadbackImage(const GLRStep &pass); + void ResizeReadbackBuffer(size_t requiredSize); + void fbo_ext_create(const GLRInitStep &step); void fbo_bind_fb_target(bool read, GLuint name); GLenum fbo_get_fb_target(bool read, GLuint **cached); diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 4e21eaf124..6c335f422a 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -13,6 +13,7 @@ #endif void GLDeleter::Perform() { + deleterMutex_.lock(); for (auto shader : shaders) { delete shader; } @@ -37,6 +38,7 @@ void GLDeleter::Perform() { delete framebuffer; } framebuffers.clear(); + deleterMutex_.unlock(); } GLRenderManager::GLRenderManager() { @@ -358,6 +360,8 @@ void GLRenderManager::Finish() { frameData.pull_condVar.notify_all(); } + frameData_[curFrame_].deleter.Take(deleter_); + curFrame_++; if (curFrame_ >= MAX_INFLIGHT_FRAMES) curFrame_ = 0; @@ -379,6 +383,10 @@ void GLRenderManager::Submit(int frame, bool triggerFence) { // When !triggerFence, we notify after syncing with Vulkan. + // Putting deletes here is safe but only because OpenGL has its own delete handling.. + // ideally we'd like to wait a frame or two. + frameData.deleter.Perform(); + if (useThread_ && triggerFence) { VLOG("PULL: Frame %d.readyForFence = true", frame); @@ -409,10 +417,6 @@ void GLRenderManager::Run(int frame) { BeginSubmitFrame(frame); FrameData &frameData = frameData_[frame]; - - // Delete stuff from the last round. - frameData.deleter_prev.Perform(); - auto &stepsOnThread = frameData_[frame].steps; auto &initStepsOnThread = frameData_[frame].initSteps; // queueRunner_.LogSteps(stepsOnThread); @@ -423,7 +427,6 @@ void GLRenderManager::Run(int frame) { switch (frameData.type) { case GLRRunType::END: - frameData.deleter_prev.Take(frameData.deleter); EndSubmitFrame(frame); break; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index b0b3b77f6c..f4355155fe 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -148,12 +148,12 @@ enum class GLRRunType { SYNC, }; -// Synchronize this externally if needed, no mutex anymore. class GLDeleter { public: void Perform(); void Take(GLDeleter &other) { + deleterMutex_.lock(); _assert_msg_(G3D, shaders.empty() && programs.empty() && buffers.empty() && textures.empty() && inputLayouts.empty() && framebuffers.empty(), "Deleter already has stuff"); shaders = std::move(other.shaders); programs = std::move(other.programs); @@ -167,6 +167,7 @@ public: other.textures.clear(); other.inputLayouts.clear(); other.framebuffers.clear(); + deleterMutex_.unlock(); } std::vector shaders; @@ -175,6 +176,7 @@ public: std::vector textures; std::vector inputLayouts; std::vector framebuffers; + std::mutex deleterMutex_; }; class GLRInputLayout { @@ -289,22 +291,22 @@ public: } void DeleteShader(GLRShader *shader) { - frameData_[curFrame_].deleter.shaders.push_back(shader); + deleter_.shaders.push_back(shader); } void DeleteProgram(GLRProgram *program) { - frameData_[curFrame_].deleter.programs.push_back(program); + deleter_.programs.push_back(program); } void DeleteBuffer(GLRBuffer *buffer) { - frameData_[curFrame_].deleter.buffers.push_back(buffer); + deleter_.buffers.push_back(buffer); } void DeleteTexture(GLRTexture *texture) { - frameData_[curFrame_].deleter.textures.push_back(texture); + deleter_.textures.push_back(texture); } void DeleteInputLayout(GLRInputLayout *inputLayout) { - frameData_[curFrame_].deleter.inputLayouts.push_back(inputLayout); + deleter_.inputLayouts.push_back(inputLayout); } void DeleteFramebuffer(GLRFramebuffer *framebuffer) { - frameData_[curFrame_].deleter.framebuffers.push_back(framebuffer); + deleter_.framebuffers.push_back(framebuffer); } void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, GLRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil); @@ -700,10 +702,7 @@ private: bool hasBegun = false; uint32_t curSwapchainImage = -1; - std::mutex deleter_mutex; GLDeleter deleter; - GLDeleter deleter_prev; - std::set activePushBuffers; }; @@ -728,6 +727,8 @@ private: bool nextFrame = false; bool firstFrame = true; + GLDeleter deleter_; + bool useThread_ = true; int curFrame_ = 0; From 8438defb24d04bcf91b7aa1c18d4e3dbb969a2cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 4 Feb 2018 13:38:44 +0100 Subject: [PATCH 104/291] Fix some memory leaks --- ext/native/thin3d/thin3d.cpp | 14 +++++++++++--- ext/native/thin3d/thin3d.h | 1 + ext/native/thin3d/thin3d_gl.cpp | 2 ++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ext/native/thin3d/thin3d.cpp b/ext/native/thin3d/thin3d.cpp index 0cde248021..98827edda9 100644 --- a/ext/native/thin3d/thin3d.cpp +++ b/ext/native/thin3d/thin3d.cpp @@ -336,17 +336,25 @@ bool DrawContext::CreatePresets() { return vsPresets_[VS_TEXTURE_COLOR_2D] && vsPresets_[VS_COLOR_2D] && fsPresets_[FS_TEXTURE_COLOR_2D] && fsPresets_[FS_COLOR_2D]; } -DrawContext::~DrawContext() { +void DrawContext::DestroyPresets() { for (int i = 0; i < VS_MAX_PRESET; i++) { - if (vsPresets_[i]) + if (vsPresets_[i]) { vsPresets_[i]->Release(); + vsPresets_[i] = nullptr; + } } for (int i = 0; i < FS_MAX_PRESET; i++) { - if (fsPresets_[i]) + if (fsPresets_[i]) { fsPresets_[i]->Release(); + fsPresets_[i] = nullptr; + } } } +DrawContext::~DrawContext() { + DestroyPresets(); +} + // TODO: SSE/NEON // Could also make C fake-simd for 64-bit, two 8888 pixels fit in a register :) void ConvertFromRGBA8888(uint8_t *dst, const uint8_t *src, uint32_t dstStride, uint32_t srcStride, uint32_t width, uint32_t height, DataFormat format) { diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 46f6aaf38e..cbd46e2d4a 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -543,6 +543,7 @@ class DrawContext { public: virtual ~DrawContext(); bool CreatePresets(); + void DestroyPresets(); virtual const DeviceCaps &GetDeviceCaps() const = 0; virtual uint32_t GetDataFormatSupport(DataFormat fmt) const = 0; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 55691e84b9..91868b4095 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -527,6 +527,7 @@ OpenGLContext::OpenGLContext() { } OpenGLContext::~OpenGLContext() { + DestroyPresets(); for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { renderManager_.UnregisterPushBuffer(i, frameData_[i].push); frameData_[i].push->Destroy(); @@ -1031,6 +1032,7 @@ DrawContext *T3DCreateGLContext() { } OpenGLInputLayout::~OpenGLInputLayout() { + render_->DeleteInputLayout(inputLayout_); } void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) { From c3629b4a538a299c39f58eba7502adb5aeb03c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Jan 2018 14:41:47 +0100 Subject: [PATCH 105/291] Warning fixes --- Common/Vulkan/VulkanMemory.cpp | 2 +- Core/Dialog/PSPSaveDialog.cpp | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Common/Vulkan/VulkanMemory.cpp b/Common/Vulkan/VulkanMemory.cpp index 1410d985a1..54c2cb6f46 100644 --- a/Common/Vulkan/VulkanMemory.cpp +++ b/Common/Vulkan/VulkanMemory.cpp @@ -359,7 +359,7 @@ void VulkanDeviceAllocator::ExecuteFree(FreeInfo *userdata) { slab.allocSizes.erase(it); } else { // Ack, a double free? - _assert_msg_(G3D, false, "Double free? Block missing at offset %d", userdata->offset); + _assert_msg_(G3D, false, "Double free? Block missing at offset %d", (int)userdata->offset); } found = true; break; diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index c9dc744843..5b80b23e79 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -395,8 +395,8 @@ void PSPSaveDialog::DisplaySaveDataInfo1() } else { char title[512]; char time[512]; - char saveTitle[512]; - char saveDetail[512]; + char saveTitle[1024]; + char saveDetail[1024]; char am_pm[] = "AM"; char hour_time[10] ; @@ -421,27 +421,27 @@ void PSPSaveDialog::DisplaySaveDataInfo1() snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm); } - snprintf(title, 512, "%s", param.GetFileInfo(currentSelectedSave).title); + snprintf(title, sizeof(title), "%s", param.GetFileInfo(currentSelectedSave).title); int day = param.GetFileInfo(currentSelectedSave).modif_time.tm_mday; int month = param.GetFileInfo(currentSelectedSave).modif_time.tm_mon + 1; int year = param.GetFileInfo(currentSelectedSave).modif_time.tm_year + 1900; s64 sizeK = param.GetFileInfo(currentSelectedSave).size / 1024; switch (g_Config.iDateFormat) { case 1: - snprintf(time, 512, "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK); + snprintf(time, sizeof(time), "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK); break; case 2: - snprintf(time, 512, "%02d/%02d/%d %s %lld KB", month, day, year, hour_time, sizeK); + snprintf(time, sizeof(time), "%02d/%02d/%d %s %lld KB", month, day, year, hour_time, sizeK); break; case 3: - snprintf(time, 512, "%02d/%02d/%d %s %lld KB", day, month, year, hour_time, sizeK); + snprintf(time, sizeof(time), "%02d/%02d/%d %s %lld KB", day, month, year, hour_time, sizeK); break; default: - snprintf(time, 512, "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK); + snprintf(time, sizeof(time), "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK); } - snprintf(saveTitle, 512, "%s", param.GetFileInfo(currentSelectedSave).saveTitle); - snprintf(saveDetail, 512, "%s", param.GetFileInfo(currentSelectedSave).saveDetail); - + snprintf(saveTitle, sizeof(saveTitle), "%s", param.GetFileInfo(currentSelectedSave).saveTitle); + snprintf(saveDetail, sizeof(saveDetail), "%s", param.GetFileInfo(currentSelectedSave).saveDetail); + PPGeDrawRect(180, 136, 480, 137, CalcFadedColor(0xFFFFFFFF)); std::string titleTxt = title; std::string timeTxt = time; From 1aa5351e34491e6d88a75b0c76e4006573455ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Jan 2018 15:40:51 +0100 Subject: [PATCH 106/291] Temporarily disable symbols on Qt, crashes strangely. --- UI/HostTypes.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/UI/HostTypes.h b/UI/HostTypes.h index 102d583ce7..e99f3e8961 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -121,7 +121,10 @@ public: #endif } virtual bool AttemptLoadSymbolMap() { - return g_symbolMap->LoadSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart)); + return false; + // TODO: Make this work with Qt and threaded GL... not sure what's so broken. + // auto fn = SymbolMapFilename(PSP_CoreParameter().fileToStart); + // return g_symbolMap->LoadSymbolMap(fn); } virtual void PrepareShutdown() { g_symbolMap->SaveSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart)); From 583c20991f5545583b48b0ba8aa37bef705afbe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Jan 2018 18:35:48 +0100 Subject: [PATCH 107/291] Qt: Some cleanup and fixes. Still not working correctly with gl-render-manager. --- Qt/QtMain.cpp | 28 +++++++++++++-------------- Qt/QtMain.h | 2 -- Qt/mainwindow.cpp | 15 ++++++++++++-- Qt/mainwindow.h | 23 +++++++++++++++++----- SDL/SDLMain.cpp | 5 ++--- UI/DevScreens.cpp | 3 +++ UI/HostTypes.h | 2 +- ext/native/thin3d/GLRenderManager.cpp | 19 ++++++++++++++++++ ext/native/thin3d/GLRenderManager.h | 3 ++- 9 files changed, 71 insertions(+), 29 deletions(-) diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index ea364b08a5..cafd80b981 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -237,7 +237,7 @@ MainUI::MainUI(QWidget *parent): MainUI::~MainUI() { - if (useThread_) { + if (emuThreadState != (int)EmuThreadState::DISABLED) { EmuThreadStop(); } #if defined(MOBILE_DEVICE) @@ -365,34 +365,32 @@ void MainUI::initializeGL() glGetError(); #endif ILOG("Initializing graphics context"); - graphicsContext = new QtDummyGraphicsContext(); - NativeInitGraphics(graphicsContext); // OpenGL uses a background thread to do the main processing and only renders on the gl thread. - useThread_ = g_Config.iGPUBackend == (int)GPUBackend::OPENGL; + graphicsContext = new QtDummyGraphicsContext(); - if (useThread_) { + NativeInitGraphics(graphicsContext); + + if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { ILOG("Using thread, starting emu thread"); EmuThreadStart(); - - graphicsContext->ThreadStart(); } else { ILOG("Not using thread, backend=%d", (int)g_Config.iGPUBackend); } + graphicsContext->ThreadStart(); } void MainUI::paintGL() { - if (useThread_) { + #ifdef SDL + SDL_PumpEvents(); + #endif + updateAccelerometer(); + if (emuThreadState == (int)EmuThreadState::DISABLED) { + UpdateRunLoop(); + } else { graphicsContext->ThreadFrame(); // Do the rest in EmuThreadFunc - } else { - #ifdef SDL - SDL_PumpEvents(); - #endif - updateAccelerometer(); - time_update(); - UpdateRunLoop(); } } diff --git a/Qt/QtMain.h b/Qt/QtMain.h index 8f0538f7c6..fc04446b00 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -131,8 +131,6 @@ private: std::thread emuThread; std::atomic emuThreadState; - - bool useThread_ = false; }; extern MainUI* emugl; diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index 7e0b481f9b..c9469c971e 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -72,6 +72,17 @@ void MainWindow::newFrame() updateMenus(); } + + std::unique_lock lock(msgMutex_); + while (!msgQueue_.empty()) { + MainWindowMsg msg = msgQueue_.front(); + msgQueue_.pop(); + switch (msg) { + case MainWindowMsg::BOOT_DONE: + bootDone(); + break; + } + } } void MainWindow::updateMenus() @@ -128,8 +139,7 @@ void MainWindow::updateMenus() emit updateMenu(); } -/* SLOTS */ -void MainWindow::Boot() +void MainWindow::bootDone() { dialogDisasm = new Debugger_Disasm(currentDebugMIPS, this, this); if(g_Config.bShowDebuggerOnLoad) @@ -149,6 +159,7 @@ void MainWindow::Boot() updateMenus(); } +/* SIGNALS */ void MainWindow::openAct() { QString filename = QFileDialog::getOpenFileName(NULL, "Load File", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.prx)"); diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index c52120820e..3e9c5469e8 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -1,5 +1,7 @@ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H +#pragma once + +#include +#include #include #include @@ -21,6 +23,11 @@ extern bool g_TakeScreenshot; class MenuAction; class MenuTree; +// hacky, should probably use qt signals or something, but whatever.. +enum class MainWindowMsg { + BOOT_DONE +}; + class MainWindow : public QMainWindow { Q_OBJECT @@ -38,6 +45,11 @@ public: void ShowMemory(u32 addr); void updateMenus(); + void Notify(MainWindowMsg msg) { + std::unique_lock lock(msgMutex_); + msgQueue_.push(msg); + } + protected: void changeEvent(QEvent *e) { @@ -54,7 +66,6 @@ signals: void updateMenu(); public slots: - void Boot(); void newFrame(); private slots: @@ -136,6 +147,7 @@ private slots: void langChanged(QAction *action) { loadLanguage(action->data().toString(), true); } private: + void bootDone(); void SetWindowScale(int zoom); void SetGameTitle(QString text); void loadLanguage(const QString &language, bool retranslate); @@ -155,6 +167,9 @@ private: QActionGroup *anisotropicGroup, *screenGroup, *displayLayoutGroup, *defaultLogGroup, *g3dLogGroup, *hleLogGroup; + + std::queue msgQueue_; + std::mutex msgMutex_; }; class MenuAction : public QAction @@ -275,5 +290,3 @@ public slots: private: const char *_text; }; - -#endif // MAINWINDOW_H diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index a3a15581e0..2ffbd44b15 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -1198,14 +1198,13 @@ int main(int argc, char *argv[]) { framecount++; } - graphicsContext->ThreadEnd(); - graphicsContext->ShutdownFromRenderThread(); - EmuThreadStop(); delete joystick; NativeShutdownGraphics(); graphicsContext->Shutdown(); + graphicsContext->ThreadEnd(); + graphicsContext->ShutdownFromRenderThread(); NativeShutdown(); delete graphicsContext; diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index 7597dd7087..b6d25ae126 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -471,6 +471,9 @@ void SystemInfoScreen::CreateViews() { #else buildConfig->Add(new InfoItem("NDEBUG", "")); #endif +#ifdef USE_ADDRESS_SANITIZER + buildConfig->Add(new InfoItem("USE_ADDRESS_SANITIZER", "")); +#endif #ifdef USING_GLES2 buildConfig->Add(new InfoItem("USING_GLES2", "")); #endif diff --git a/UI/HostTypes.h b/UI/HostTypes.h index e99f3e8961..c236a1baac 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -110,7 +110,7 @@ public: // this is sent from EMU thread! Make sure that Host handles it properly! virtual void BootDone() { g_symbolMap->SortSymbols(); - mainWindow->Boot(); + mainWindow->Notify(MainWindowMsg::BOOT_DONE); } virtual bool IsDebuggingEnabled() { diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 6c335f422a..67da177dba 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -69,10 +69,29 @@ void GLRenderManager::ThreadStart() { } void GLRenderManager::ThreadEnd() { + ILOG("ThreadEnd"); + // Wait for any shutdown to complete in StopThread(). std::unique_lock lock(mutex_); queueRunner_.DestroyDeviceObjects(); VLOG("PULL: Quitting"); + + // Good point to run all the deleters to get rid of leftover objects. + for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { + frameData_[i].deleter.Perform(); + for (int j = 0; j < (int)frameData_[i].steps.size(); j++) { + delete frameData_[i].steps[j]; + } + frameData_[i].steps.clear(); + frameData_[i].initSteps.clear(); + } + deleter_.Perform(); + + for (int i = 0; i < (int)steps_.size(); i++) { + delete steps_[i]; + } + steps_.clear(); + initSteps_.clear(); } bool GLRenderManager::ThreadFrame() { diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index f4355155fe..fe16fa9687 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -10,6 +10,7 @@ #include #include +#include "base/logging.h" #include "gfx/gl_common.h" #include "math/dataconv.h" #include "Common/Log.h" @@ -701,7 +702,7 @@ private: // Swapchain. bool hasBegun = false; uint32_t curSwapchainImage = -1; - + GLDeleter deleter; std::set activePushBuffers; }; From c16e397fc64cb0ddf19f6986ba5cea1e4db16517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 4 Feb 2018 12:00:56 +0100 Subject: [PATCH 108/291] SDL: NativeInitGraphics/NativeShutdownGraphics should run on the emu thread. --- SDL/SDLMain.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 2ffbd44b15..098b02dcac 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -725,21 +725,26 @@ enum class EmuThreadState { static std::thread emuThread; static std::atomic emuThreadState((int)EmuThreadState::DISABLED); -static void EmuThreadFunc() { +static void EmuThreadFunc(GraphicsContext *graphicsContext) { setCurrentThreadName("Emu"); // There's no real requirement that NativeInit happen on this thread. // We just call the update/render loop here. emuThreadState = (int)EmuThreadState::RUNNING; + + NativeInitGraphics(graphicsContext); + while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) { UpdateRunLoop(); } emuThreadState = (int)EmuThreadState::STOPPED; + + NativeShutdownGraphics(); } -static void EmuThreadStart() { +static void EmuThreadStart(GraphicsContext *context) { emuThreadState = (int)EmuThreadState::START_REQUESTED; - emuThread = std::thread(&EmuThreadFunc); + emuThread = std::thread(&EmuThreadFunc, context); } static void EmuThreadStop() { @@ -923,6 +928,9 @@ int main(int argc, char *argv[]) { GraphicsContext *graphicsContext = nullptr; SDL_Window *window = nullptr; + + bool useEmuThread; + std::string error_message; if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { SDLGLGraphicsContext *ctx = new SDLGLGraphicsContext(); @@ -930,6 +938,7 @@ int main(int argc, char *argv[]) { printf("GL init error '%s'\n", error_message.c_str()); } graphicsContext = ctx; + useEmuThread = true; } else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext(); if (!ctx->Init(window, x, y, mode, &error_message)) { @@ -943,6 +952,7 @@ int main(int argc, char *argv[]) { } else { graphicsContext = ctx; } + useEmuThread = false; } // Since we render from the main thread, there's nothing done here, but we call it to avoid confusion. @@ -956,9 +966,10 @@ int main(int argc, char *argv[]) { SDL_ShowCursor(SDL_DISABLE); #endif - NativeInitGraphics(graphicsContext); - - NativeResized(); + if (!useEmuThread) { + NativeInitGraphics(graphicsContext); + NativeResized(); + } SDL_AudioSpec fmt, ret_fmt; memset(&fmt, 0, sizeof(fmt)); @@ -996,8 +1007,8 @@ int main(int argc, char *argv[]) { int framecount = 0; bool mouseDown = false; - if (GetGPUBackend() == GPUBackend::OPENGL) { - EmuThreadStart(); + if (useEmuThread) { + EmuThreadStart(graphicsContext); } graphicsContext->ThreadStart(); @@ -1201,7 +1212,6 @@ int main(int argc, char *argv[]) { EmuThreadStop(); delete joystick; - NativeShutdownGraphics(); graphicsContext->Shutdown(); graphicsContext->ThreadEnd(); graphicsContext->ShutdownFromRenderThread(); From 85446d6c513a7f5df575c35462d7fc132107cfd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 4 Feb 2018 12:26:35 +0100 Subject: [PATCH 109/291] Split the SDL graphics contexts into their own files. --- CMakeLists.txt | 4 +- SDL/SDLGLGraphicsContext.cpp | 128 ++++++++++++ SDL/SDLMain.cpp | 329 +------------------------------ SDL/SDLVulkanGraphicsContext.cpp | 111 +++++++++++ SDL/SDLVulkanGraphicsContext.h | 53 +++++ SDLGLGraphicsContext.h | 56 ++++++ 6 files changed, 359 insertions(+), 322 deletions(-) create mode 100644 SDL/SDLGLGraphicsContext.cpp create mode 100644 SDL/SDLVulkanGraphicsContext.cpp create mode 100644 SDL/SDLVulkanGraphicsContext.h create mode 100644 SDLGLGraphicsContext.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 95db991510..bf9b4c99c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -776,7 +776,9 @@ elseif(TARGET SDL2::SDL2) set(nativeExtra ${nativeExtra} SDL/SDLJoystick.h SDL/SDLJoystick.cpp - SDL/SDLMain.cpp) + SDL/SDLMain.cpp + SDL/SDLGLGraphicsContext.cpp + SDL/SDLVulkanGraphicsContext.cpp) set(nativeExtraLibs ${nativeExtraLibs} SDL2::SDL2) if(APPLE) set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm) diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp new file mode 100644 index 0000000000..51cbde1470 --- /dev/null +++ b/SDL/SDLGLGraphicsContext.cpp @@ -0,0 +1,128 @@ +#include "SDLGLGraphicsContext.h" +#include "Core/Config.h" +#include "Core/System.h" +#include "base/NativeApp.h" +#include "base/display.h" +#include "gfx_es2/gpu_features.h" + +class GLRenderManager; + +// Returns 0 on success. +int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) { + struct GLVersionPair { + int major; + int minor; + }; + GLVersionPair attemptVersions[] = { +#ifdef USING_GLES2 + {3, 2}, {3, 1}, {3, 0}, {2, 0}, +#else + {4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, + {3, 3}, {3, 2}, {3, 1}, {3, 0}, +#endif + }; + +#ifdef USING_GLES2 + mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN; +#else + mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; +#endif + SDL_GLContext glContext = nullptr; + for (size_t i = 0; i < ARRAY_SIZE(attemptVersions); ++i) { + const auto &ver = attemptVersions[i]; + // Make sure to request a somewhat modern GL context at least - the + // latest supported by MacOS X (really, really sad...) + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, ver.major); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, ver.minor); +#ifdef USING_GLES2 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SetGLCoreContext(false); +#else + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SetGLCoreContext(true); +#endif + + window = SDL_CreateWindow("PPSSPP", x,y, pixel_xres, pixel_yres, mode); + if (!window) { + NativeShutdown(); + fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); + continue; + } + + glContext = SDL_GL_CreateContext(window); + if (glContext != nullptr) { + // Victory, got one. + break; + } + + // Let's keep trying. To be safe, destroy the window - docs say needed to change profile. + // in practice, it doesn't seem to matter, but maybe it differs by platform. + SDL_DestroyWindow(window); + } + + if (glContext == nullptr) { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SetGLCoreContext(false); + + window = SDL_CreateWindow("PPSSPP", x,y, pixel_xres, pixel_yres, mode); + if (window == nullptr) { + NativeShutdown(); + fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); + SDL_Quit(); + return 2; + } + + glContext = SDL_GL_CreateContext(window); + if (glContext == nullptr) { + NativeShutdown(); + fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError()); + SDL_Quit(); + return 2; + } + } + +#ifdef USING_EGL + EGL_Init(); +#endif + +#ifndef USING_GLES2 + // Some core profile drivers elide certain extensions from GL_EXTENSIONS/etc. + // glewExperimental allows us to force GLEW to search for the pointers anyway. + if (gl_extensions.IsCoreContext) { + glewExperimental = true; + } + if (GLEW_OK != glewInit()) { + printf("Failed to initialize glew!\n"); + return 1; + } + // Unfortunately, glew will generate an invalid enum error, ignore. + if (gl_extensions.IsCoreContext) + glGetError(); + + if (GLEW_VERSION_2_0) { + printf("OpenGL 2.0 or higher.\n"); + } else { + printf("Sorry, this program requires OpenGL 2.0.\n"); + return 1; + } +#endif + + // Finally we can do the regular initialization. + CheckGLExtensions(); + draw_ = Draw::T3DCreateGLContext(); + renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + SetGPUBackend(GPUBackend::OPENGL); + bool success = draw_->CreatePresets(); + assert(success); + renderManager_->SetSwapFunction([&]() { +#ifdef USING_EGL + eglSwapBuffers(g_eglDisplay, g_eglSurface); +#else + SDL_GL_SwapWindow(window_); +#endif + }); + window_ = window; + return 0; +} diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 098b02dcac..67da77c12c 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -24,20 +24,15 @@ SDLJoystick *joystick = NULL; #include "base/logging.h" #include "base/timeutil.h" #include "ext/glslang/glslang/Public/ShaderLang.h" -#include "gfx/gl_common.h" -#include "gfx_es2/gpu_features.h" #include "input/input_state.h" #include "input/keycodes.h" #include "net/resolve.h" #include "base/NKCodeFromSDL.h" #include "util/const_map.h" #include "util/text/utf8.h" -#include "util/text/parsers.h" #include "math/math_util.h" #include "thin3d/GLRenderManager.h" #include "thread/threadutil.h" -#include "Common/Vulkan/VulkanContext.h" -#include "Common/Vulkan/VulkanDebug.h" #include "math.h" #if !defined(__APPLE__) @@ -61,6 +56,9 @@ SDLJoystick *joystick = NULL; #include "Core/Core.h" #include "Core/Config.h" #include "Common/GraphicsContext.h" +#include "SDLGLGraphicsContext.h" +#include "SDLVulkanGraphicsContext.h" + GlobalUIState lastUIState = UISTATE_MENU; GlobalUIState GetUIState(); @@ -72,8 +70,6 @@ static int g_QuitRequested = 0; static int g_DesktopWidth = 0; static int g_DesktopHeight = 0; -static VulkanLogOptions g_LogOptions; - #if defined(USING_EGL) static EGLDisplay g_eglDisplay = NULL; @@ -202,318 +198,6 @@ void EGL_Close() { } #endif -class GLRenderManager; - -class SDLGLGraphicsContext : public DummyGraphicsContext { -public: - SDLGLGraphicsContext() { - } - ~SDLGLGraphicsContext() { - delete draw_; - } - - // Returns 0 on success. - int Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message); - - void Shutdown() override { -#ifdef USING_EGL - EGL_Close(); -#else - SDL_GL_DeleteContext(glContext); -#endif - } - - void SwapBuffers() override { - renderManager_->Swap(); - } - - Draw::DrawContext *GetDrawContext() override { - return draw_; - } - - void ThreadStart() override { - renderManager_->ThreadStart(); - } - - bool ThreadFrame() override { - return renderManager_->ThreadFrame(); - } - - void ThreadEnd() override { - renderManager_->ThreadEnd(); - } - -private: - Draw::DrawContext *draw_ = nullptr; - SDL_Window *window_; - SDL_GLContext glContext = nullptr; - GLRenderManager *renderManager_ = nullptr; -}; - -// Returns 0 on success. -int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) { - struct GLVersionPair { - int major; - int minor; - }; - GLVersionPair attemptVersions[] = { -#ifdef USING_GLES2 - {3, 2}, {3, 1}, {3, 0}, {2, 0}, -#else - {4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, - {3, 3}, {3, 2}, {3, 1}, {3, 0}, -#endif - }; - -#ifdef USING_GLES2 - mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN; -#else - mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; -#endif - SDL_GLContext glContext = nullptr; - for (size_t i = 0; i < ARRAY_SIZE(attemptVersions); ++i) { - const auto &ver = attemptVersions[i]; - // Make sure to request a somewhat modern GL context at least - the - // latest supported by MacOS X (really, really sad...) - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, ver.major); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, ver.minor); -#ifdef USING_GLES2 - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SetGLCoreContext(false); -#else - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SetGLCoreContext(true); -#endif - - window = SDL_CreateWindow("PPSSPP", x,y, pixel_xres, pixel_yres, mode); - if (!window) { - NativeShutdown(); - fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); - continue; - } - - glContext = SDL_GL_CreateContext(window); - if (glContext != nullptr) { - // Victory, got one. - break; - } - - // Let's keep trying. To be safe, destroy the window - docs say needed to change profile. - // in practice, it doesn't seem to matter, but maybe it differs by platform. - SDL_DestroyWindow(window); - } - - if (glContext == nullptr) { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 0); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - SetGLCoreContext(false); - - window = SDL_CreateWindow("PPSSPP", x,y, pixel_xres, pixel_yres, mode); - if (window == nullptr) { - NativeShutdown(); - fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); - SDL_Quit(); - return 2; - } - - glContext = SDL_GL_CreateContext(window); - if (glContext == nullptr) { - NativeShutdown(); - fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError()); - SDL_Quit(); - return 2; - } - } - -#ifdef USING_EGL - EGL_Init(); -#endif - -#ifndef USING_GLES2 - // Some core profile drivers elide certain extensions from GL_EXTENSIONS/etc. - // glewExperimental allows us to force GLEW to search for the pointers anyway. - if (gl_extensions.IsCoreContext) { - glewExperimental = true; - } - if (GLEW_OK != glewInit()) { - printf("Failed to initialize glew!\n"); - return 1; - } - // Unfortunately, glew will generate an invalid enum error, ignore. - if (gl_extensions.IsCoreContext) - glGetError(); - - if (GLEW_VERSION_2_0) { - printf("OpenGL 2.0 or higher.\n"); - } else { - printf("Sorry, this program requires OpenGL 2.0.\n"); - return 1; - } -#endif - - // Finally we can do the regular initialization. - CheckGLExtensions(); - draw_ = Draw::T3DCreateGLContext(); - renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - SetGPUBackend(GPUBackend::OPENGL); - bool success = draw_->CreatePresets(); - assert(success); - renderManager_->SetSwapFunction([&]() { -#ifdef USING_EGL - eglSwapBuffers(g_eglDisplay, g_eglSurface); -#else - SDL_GL_SwapWindow(window_); -#endif - }); - window_ = window; - return 0; -} - -class SDLVulkanGraphicsContext : public GraphicsContext { -public: - SDLVulkanGraphicsContext() {} - ~SDLVulkanGraphicsContext() { - delete draw_; - } - - bool Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message); - - void Shutdown() override; - - void SwapBuffers() override { - // We don't do it this way. - } - - void Resize() override { - /* - draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); - vulkan_->DestroyObjects(); - // TODO: Take from real window dimensions - int width = 1024; - int height = 768; - vulkan_->ReinitSurface(width, height); - vulkan_->InitObjects(); - draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); - */ - } - - void SwapInterval(int interval) override { - } - void *GetAPIContext() override { - return vulkan_; - } - - Draw::DrawContext *GetDrawContext() override { - return draw_; - } -private: - Draw::DrawContext *draw_ = nullptr; - VulkanContext *vulkan_ = nullptr; -}; - -bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) { - window = SDL_CreateWindow("Initializing Vulkan...", x, y, pixel_xres, pixel_yres, mode); - if (!window) { - fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError()); - exit(1); - } - - init_glslang(); - - g_LogOptions.breakOnError = true; - g_LogOptions.breakOnWarning = true; - g_LogOptions.msgBoxOnError = false; - - Version gitVer(PPSSPP_GIT_VERSION); - - vulkan_ = new VulkanContext(); - if (vulkan_->InitError().size()) { - *error_message = vulkan_->InitError(); - delete vulkan_; - vulkan_ = nullptr; - return false; - } - - int vulkanFlags = VULKAN_FLAG_PRESENT_MAILBOX; - // vulkanFlags |= VULKAN_FLAG_VALIDATE; - VulkanContext::CreateInfo info{}; - info.app_name = "PPSSPP"; - info.app_ver = gitVer.ToInteger(); - info.flags = vulkanFlags; - if (VK_SUCCESS != vulkan_->CreateInstance(info)) { - *error_message = vulkan_->InitError(); - delete vulkan_; - vulkan_ = nullptr; - return false; - } - vulkan_->ChooseDevice(vulkan_->GetBestPhysicalDevice()); - if (vulkan_->CreateDevice() != VK_SUCCESS) { - *error_message = vulkan_->InitError(); - delete vulkan_; - vulkan_ = nullptr; - return false; - } - -#if !defined(__APPLE__) - SDL_SysWMinfo sys_info{}; - SDL_VERSION(&sys_info.version); //Set SDL version - if (!SDL_GetWindowWMInfo(window, &sys_info)) { - fprintf(stderr, "Error getting SDL window wm info: %s\n", SDL_GetError()); - exit(1); - } - switch (sys_info.subsystem) { - case SDL_SYSWM_X11: -#if defined(VK_USE_PLATFORM_XLIB_KHR) - vulkan_->InitSurface(WINDOWSYSTEM_XLIB, (void*)sys_info.info.x11.display, - (void *)(intptr_t)sys_info.info.x11.window, pixel_xres, pixel_yres); -#elif defined(VK_USE_PLATFORM_XCB_KHR) - vulkan_->InitSurface(WINDOWSYSTEM_XCB, (void*)XGetXCBConnection(sys_info.info.x11.display), - (void *)(intptr_t)sys_info.info.x11.window, pixel_xres, pixel_yres); -#endif - break; -#if defined(VK_USE_PLATFORM_WAYLAND_KHR) - case SDL_SYSWM_WAYLAND: - vulkan_->InitSurface(WINDOWSYSTEM_WAYLAND, (void*)sys_info.info.wl.display, - (void *)sys_info.info.wl.surface, pixel_xres, pixel_yres); - break; -#endif - default: - fprintf(stderr, "Vulkan subsystem %d not supported\n", sys_info.subsystem); - exit(1); - break; - } -#endif - - if (!vulkan_->InitObjects()) { - *error_message = vulkan_->InitError(); - Shutdown(); - return false; - } - - draw_ = Draw::T3DCreateVulkanContext(vulkan_, false); - SetGPUBackend(GPUBackend::VULKAN); - bool success = draw_->CreatePresets(); - assert(success); - draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); - - return true; -} - -void SDLVulkanGraphicsContext::Shutdown() { - if (draw_) - draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); - delete draw_; - draw_ = nullptr; - vulkan_->WaitUntilQueueIdle(); - vulkan_->DestroyObjects(); - vulkan_->DestroyDevice(); - vulkan_->DestroyDebugMsgCallback(); - vulkan_->DestroyInstance(); - delete vulkan_; - vulkan_ = nullptr; - finalize_glslang(); -} int getDisplayNumber(void) { int displayNumber = 0; @@ -522,8 +206,7 @@ int getDisplayNumber(void) { //get environment displayNumberStr=getenv("SDL_VIDEO_FULLSCREEN_HEAD"); - if (displayNumberStr) - { + if (displayNumberStr) { displayNumber = atoi(displayNumberStr); } @@ -1212,6 +895,10 @@ int main(int argc, char *argv[]) { EmuThreadStop(); delete joystick; + + if (!useEmuThread) { + NativeShutdownGraphics(); + } graphicsContext->Shutdown(); graphicsContext->ThreadEnd(); graphicsContext->ShutdownFromRenderThread(); diff --git a/SDL/SDLVulkanGraphicsContext.cpp b/SDL/SDLVulkanGraphicsContext.cpp new file mode 100644 index 0000000000..2c868b2a37 --- /dev/null +++ b/SDL/SDLVulkanGraphicsContext.cpp @@ -0,0 +1,111 @@ +#include "Core/Config.h" +#include "base/NativeApp.h" +#include "base/display.h" +#include "thin3d/thin3d.h" +#include "util/text/parsers.h" + +#include "Core/System.h" +#include "SDLVulkanGraphicsContext.h" + +bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) { + window = SDL_CreateWindow("Initializing Vulkan...", x, y, pixel_xres, pixel_yres, mode); + if (!window) { + fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError()); + exit(1); + } + + init_glslang(); + + g_LogOptions.breakOnError = true; + g_LogOptions.breakOnWarning = true; + g_LogOptions.msgBoxOnError = false; + + Version gitVer(PPSSPP_GIT_VERSION); + + vulkan_ = new VulkanContext(); + if (vulkan_->InitError().size()) { + *error_message = vulkan_->InitError(); + delete vulkan_; + vulkan_ = nullptr; + return false; + } + + int vulkanFlags = VULKAN_FLAG_PRESENT_MAILBOX; + // vulkanFlags |= VULKAN_FLAG_VALIDATE; + VulkanContext::CreateInfo info{}; + info.app_name = "PPSSPP"; + info.app_ver = gitVer.ToInteger(); + info.flags = vulkanFlags; + if (VK_SUCCESS != vulkan_->CreateInstance(info)) { + *error_message = vulkan_->InitError(); + delete vulkan_; + vulkan_ = nullptr; + return false; + } + vulkan_->ChooseDevice(vulkan_->GetBestPhysicalDevice()); + if (vulkan_->CreateDevice() != VK_SUCCESS) { + *error_message = vulkan_->InitError(); + delete vulkan_; + vulkan_ = nullptr; + return false; + } + +#if !defined(__APPLE__) + SDL_SysWMinfo sys_info{}; + SDL_VERSION(&sys_info.version); //Set SDL version + if (!SDL_GetWindowWMInfo(window, &sys_info)) { + fprintf(stderr, "Error getting SDL window wm info: %s\n", SDL_GetError()); + exit(1); + } + switch (sys_info.subsystem) { + case SDL_SYSWM_X11: +#if defined(VK_USE_PLATFORM_XLIB_KHR) + vulkan_->InitSurface(WINDOWSYSTEM_XLIB, (void*)sys_info.info.x11.display, + (void *)(intptr_t)sys_info.info.x11.window, pixel_xres, pixel_yres); +#elif defined(VK_USE_PLATFORM_XCB_KHR) + vulkan_->InitSurface(WINDOWSYSTEM_XCB, (void*)XGetXCBConnection(sys_info.info.x11.display), + (void *)(intptr_t)sys_info.info.x11.window, pixel_xres, pixel_yres); +#endif + break; +#if defined(VK_USE_PLATFORM_WAYLAND_KHR) + case SDL_SYSWM_WAYLAND: + vulkan_->InitSurface(WINDOWSYSTEM_WAYLAND, (void*)sys_info.info.wl.display, + (void *)sys_info.info.wl.surface, pixel_xres, pixel_yres); + break; +#endif + default: + fprintf(stderr, "Vulkan subsystem %d not supported\n", sys_info.subsystem); + exit(1); + break; + } +#endif + + if (!vulkan_->InitObjects()) { + *error_message = vulkan_->InitError(); + Shutdown(); + return false; + } + + draw_ = Draw::T3DCreateVulkanContext(vulkan_, false); + SetGPUBackend(GPUBackend::VULKAN); + bool success = draw_->CreatePresets(); + assert(success); + draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + + return true; +} + +void SDLVulkanGraphicsContext::Shutdown() { + if (draw_) + draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + delete draw_; + draw_ = nullptr; + vulkan_->WaitUntilQueueIdle(); + vulkan_->DestroyObjects(); + vulkan_->DestroyDevice(); + vulkan_->DestroyDebugMsgCallback(); + vulkan_->DestroyInstance(); + delete vulkan_; + vulkan_ = nullptr; + finalize_glslang(); +} diff --git a/SDL/SDLVulkanGraphicsContext.h b/SDL/SDLVulkanGraphicsContext.h new file mode 100644 index 0000000000..42883b6700 --- /dev/null +++ b/SDL/SDLVulkanGraphicsContext.h @@ -0,0 +1,53 @@ +#include "SDL.h" +#if !defined(__APPLE__) +#include "SDL_syswm.h" +#endif + +#include "Common/GraphicsContext.h" +#include "Common/Vulkan/VulkanContext.h" +#include "Common/Vulkan/VulkanDebug.h" + +#include "thin3d/thin3d.h" + +class SDLVulkanGraphicsContext : public GraphicsContext { +public: + SDLVulkanGraphicsContext() {} + ~SDLVulkanGraphicsContext() { + delete draw_; + } + + bool Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message); + + void Shutdown() override; + + void SwapBuffers() override { + // We don't do it this way. + } + + void Resize() override { + /* + draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + vulkan_->DestroyObjects(); + // TODO: Take from real window dimensions + int width = 1024; + int height = 768; + vulkan_->ReinitSurface(width, height); + vulkan_->InitObjects(); + draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + */ + } + + void SwapInterval(int interval) override { + } + void *GetAPIContext() override { + return vulkan_; + } + + Draw::DrawContext *GetDrawContext() override { + return draw_; + } +private: + Draw::DrawContext *draw_ = nullptr; + VulkanContext *vulkan_ = nullptr; + VulkanLogOptions g_LogOptions; +}; diff --git a/SDLGLGraphicsContext.h b/SDLGLGraphicsContext.h new file mode 100644 index 0000000000..30518585e1 --- /dev/null +++ b/SDLGLGraphicsContext.h @@ -0,0 +1,56 @@ +#if !defined(__APPLE__) +#include "SDL_syswm.h" +#endif +#include "SDL.h" + +#include "thin3d/GLRenderManager.h" +#include "gfx/gl_common.h" +#include "Common/GraphicsContext.h" + +class SDLGLGraphicsContext : public DummyGraphicsContext { +public: + SDLGLGraphicsContext() { + } + ~SDLGLGraphicsContext() { + delete draw_; + } + + // Returns 0 on success. + int Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message); + + void Shutdown() override { +#ifdef USING_EGL + EGL_Close(); +#else + SDL_GL_DeleteContext(glContext); +#endif + } + + void SwapBuffers() override { + renderManager_->Swap(); + } + + Draw::DrawContext *GetDrawContext() override { + return draw_; + } + + void ThreadStart() override { + renderManager_->ThreadStart(); + } + + bool ThreadFrame() override { + return renderManager_->ThreadFrame(); + } + + void ThreadEnd() override { + renderManager_->ThreadEnd(); + } + +private: + Draw::DrawContext *draw_ = nullptr; + SDL_Window *window_; + SDL_GLContext glContext = nullptr; + GLRenderManager *renderManager_ = nullptr; +}; + + From 99386da01e155fb5b15a7da7cdc893d1b40a263a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 4 Feb 2018 13:04:21 +0100 Subject: [PATCH 110/291] Minor cleanups --- SDL/SDLGLGraphicsContext.cpp | 14 ++++++++++++++ SDLGLGraphicsContext.h | 12 ++---------- ext/native/thin3d/GLRenderManager.cpp | 2 +- ext/native/thin3d/GLRenderManager.h | 3 +++ ext/native/thin3d/thin3d_gl.cpp | 4 ++-- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp index 51cbde1470..f8f69fd02c 100644 --- a/SDL/SDLGLGraphicsContext.cpp +++ b/SDL/SDLGLGraphicsContext.cpp @@ -126,3 +126,17 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std: window_ = window; return 0; } + +void SDLGLGraphicsContext::Shutdown() { +} + +void SDLGLGraphicsContext::ShutdownFromRenderThread() { + delete draw_; + draw_ = nullptr; + +#ifdef USING_EGL + EGL_Close(); +#else + SDL_GL_DeleteContext(glContext); +#endif +} diff --git a/SDLGLGraphicsContext.h b/SDLGLGraphicsContext.h index 30518585e1..71f130a4f7 100644 --- a/SDLGLGraphicsContext.h +++ b/SDLGLGraphicsContext.h @@ -11,20 +11,12 @@ class SDLGLGraphicsContext : public DummyGraphicsContext { public: SDLGLGraphicsContext() { } - ~SDLGLGraphicsContext() { - delete draw_; - } // Returns 0 on success. int Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message); - void Shutdown() override { -#ifdef USING_EGL - EGL_Close(); -#else - SDL_GL_DeleteContext(glContext); -#endif - } + void Shutdown() override; + void ShutdownFromRenderThread() override; void SwapBuffers() override { renderManager_->Swap(); diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 67da177dba..ef802f4729 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -54,7 +54,7 @@ GLRenderManager::GLRenderManager() { GLRenderManager::~GLRenderManager() { for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { - + // _assert_(frameData_[i].deleter.IsEmpty()); } if (!useThread_) { diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index fe16fa9687..87b4b0bb8c 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -194,6 +194,9 @@ public: int semanticsMask_ = 0; }; +// Note: The GLRenderManager is created and destroyed on the render thread, and the latter +// happens after the emu thread has been destroyed. Therefore, it's safe to run wild deleting stuff +// directly in the destructor. class GLRenderManager { public: GLRenderManager(); diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 91868b4095..9799d8de4a 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -477,7 +477,7 @@ private: OpenGLTexture *boundTextures_[8]{}; int maxTextures_ = 0; DeviceCaps caps_{}; - + // Bound state OpenGLPipeline *curPipeline_ = nullptr; OpenGLBuffer *curVBuffers_[4]{}; @@ -519,7 +519,7 @@ OpenGLContext::OpenGLContext() { default: caps_.vendor = GPUVendor::VENDOR_UNKNOWN; break; - } + } for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { frameData_[i].push = new GLPushBuffer(&renderManager_, GL_ARRAY_BUFFER, 64 * 1024); renderManager_.RegisterPushBuffer(i, frameData_[i].push); From 79d1610148c26f8b5716ed452f7af4f832e918ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 4 Feb 2018 13:07:55 +0100 Subject: [PATCH 111/291] Move SDLGLGraphicsContext.h to the correct location. Minor cleanup --- SDLGLGraphicsContext.h => SDL/SDLGLGraphicsContext.h | 0 ext/native/thin3d/GLRenderManager.cpp | 2 +- ext/native/thin3d/GLRenderManager.h | 5 ++++- 3 files changed, 5 insertions(+), 2 deletions(-) rename SDLGLGraphicsContext.h => SDL/SDLGLGraphicsContext.h (100%) diff --git a/SDLGLGraphicsContext.h b/SDL/SDLGLGraphicsContext.h similarity index 100% rename from SDLGLGraphicsContext.h rename to SDL/SDLGLGraphicsContext.h diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index ef802f4729..9fdc146846 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -54,7 +54,7 @@ GLRenderManager::GLRenderManager() { GLRenderManager::~GLRenderManager() { for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { - // _assert_(frameData_[i].deleter.IsEmpty()); + _assert_(frameData_[i].deleter.IsEmpty()); } if (!useThread_) { diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 87b4b0bb8c..670ecd72f7 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -153,9 +153,12 @@ class GLDeleter { public: void Perform(); + bool IsEmpty() const { + return shaders.empty() && programs.empty() && buffers.empty() && textures.empty() && inputLayouts.empty() && framebuffers.empty(); + } void Take(GLDeleter &other) { deleterMutex_.lock(); - _assert_msg_(G3D, shaders.empty() && programs.empty() && buffers.empty() && textures.empty() && inputLayouts.empty() && framebuffers.empty(), "Deleter already has stuff"); + _assert_msg_(G3D, IsEmpty(), "Deleter already has stuff"); shaders = std::move(other.shaders); programs = std::move(other.programs); buffers = std::move(other.buffers); From 020eb9d86ca09bf557599171aebe91a9b132767a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 4 Feb 2018 13:38:58 +0100 Subject: [PATCH 112/291] Fix further memory leaks --- SDL/SDLMain.cpp | 1 + ext/native/thin3d/GLRenderManager.cpp | 3 +++ ext/native/thin3d/thin3d_gl.cpp | 1 + 3 files changed, 5 insertions(+) diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 67da77c12c..e6258fbe7d 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -913,5 +913,6 @@ int main(int argc, char *argv[]) { #endif glslang::FinalizeProcess(); + ILOG("Leaving main"); return 0; } diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 9fdc146846..e4a4ab23ae 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -56,6 +56,9 @@ GLRenderManager::~GLRenderManager() { for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { _assert_(frameData_[i].deleter.IsEmpty()); } + // Was anything deleted during shutdown? + deleter_.Perform(); + // _assert_(deleter_.IsEmpty()); if (!useThread_) { // The main thread is also the render thread. diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 9799d8de4a..6d81a98c6e 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -297,6 +297,7 @@ public: OpenGLPipeline(GLRenderManager *render) : render_(render) { } ~OpenGLPipeline() { + ILOG("OpenGLPipeline released"); for (auto &iter : shaders) { iter->Release(); } From 903abe8779dd67acc221bb9b54eded918a83a18d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 4 Feb 2018 13:54:10 +0100 Subject: [PATCH 113/291] Qt: Prevent some race conditions on shutdown by deleting emugl. --- Qt/QtMain.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index cafd80b981..16f3292a84 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -140,8 +140,7 @@ float CalculateDPIScale() #endif } -static int mainInternal(QApplication &a) -{ +static int mainInternal(QApplication &a) { #ifdef MOBILE_DEVICE emugl = new MainUI(); emugl->resize(pixel_xres, pixel_yres); @@ -186,15 +185,19 @@ static int mainInternal(QApplication &a) QScopedPointer audio(new MainAudio()); audio->run(); #endif - return a.exec(); + int retval = a.exec(); + delete emugl; + return retval; } void MainUI::EmuThreadFunc() { ILOG("In emu thread"); setCurrentThreadName("Emu"); - // There's no real requirement that NativeInit happen on this thread. - // We just call the update/render loop here. + // There's no real requirement that NativeInit happen on this thread, though it can't hurt... + // We just call the update/render loop here. NativeInitGraphics should be here though. + NativeInitGraphics(graphicsContext); + emuThreadState = (int)EmuThreadState::RUNNING; while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) { #ifdef SDL @@ -204,6 +207,8 @@ void MainUI::EmuThreadFunc() { time_update(); UpdateRunLoop(); } + NativeShutdownGraphics(); + emuThreadState = (int)EmuThreadState::STOPPED; } @@ -237,13 +242,14 @@ MainUI::MainUI(QWidget *parent): MainUI::~MainUI() { + ILOG("MainUI::Destructor"); if (emuThreadState != (int)EmuThreadState::DISABLED) { + ILOG("EmuThreadStop"); EmuThreadStop(); } #if defined(MOBILE_DEVICE) delete acc; #endif - NativeShutdownGraphics(); graphicsContext->Shutdown(); delete graphicsContext; graphicsContext = nullptr; @@ -369,8 +375,6 @@ void MainUI::initializeGL() // OpenGL uses a background thread to do the main processing and only renders on the gl thread. graphicsContext = new QtDummyGraphicsContext(); - NativeInitGraphics(graphicsContext); - if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { ILOG("Using thread, starting emu thread"); EmuThreadStart(); @@ -516,8 +520,8 @@ int main(int argc, char *argv[]) g_Config.iGPUBackend = (int)GPUBackend::OPENGL; int ret = mainInternal(a); + ILOG("Left mainInternal here."); - NativeShutdownGraphics(); #ifdef SDL SDL_PauseAudio(1); SDL_CloseAudio(); From d30f1c2019a5c10321aca0e3e01a12f04fb4be22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 4 Feb 2018 14:13:47 +0100 Subject: [PATCH 114/291] Fix another Qt memory leak --- ext/native/gfx_es2/draw_text_qt.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ext/native/gfx_es2/draw_text_qt.cpp b/ext/native/gfx_es2/draw_text_qt.cpp index 7b523f47ab..7b6ca82561 100644 --- a/ext/native/gfx_es2/draw_text_qt.cpp +++ b/ext/native/gfx_es2/draw_text_qt.cpp @@ -140,6 +140,12 @@ void TextDrawerQt::ClearCache() { } cache_.clear(); sizeCache_.clear(); + // Also wipe the font map. + for (auto iter : fontMap_) { + delete iter.second; + } + fontMap_.clear(); + fontHash_ = 0; } void TextDrawerQt::DrawStringRect(DrawBuffer &target, const char *str, const Bounds &bounds, uint32_t color, int align) { From 3e56d8bbdf0adfa268ee0a74cbe03ca21d8be31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 5 Feb 2018 16:21:39 +0100 Subject: [PATCH 115/291] Noticed that the UWP build has been broken for some time, fix it. Should probably set up a buildbot if we care about this... --- Core/Core.cpp | 2 +- GPU/GPUState.cpp | 1 - UI/DisplayLayoutScreen.cpp | 2 +- UI/EmuScreen.cpp | 9 ++++--- UI/GameSettingsScreen.cpp | 2 +- UWP/GPU_UWP/GPU_UWP.vcxproj | 2 ++ UWP/GPU_UWP/GPU_UWP.vcxproj.filters | 6 +++++ UWP/NativeUWP/NativeUWP.vcxproj | 2 -- UWP/NativeUWP/NativeUWP.vcxproj.filters | 6 ----- UWP/PPSSPP_UWPMain.cpp | 5 ++-- ext/native/base/timeutil.cpp | 33 ------------------------- ext/native/thin3d/GLQueueRunner.cpp | 2 +- 12 files changed, 19 insertions(+), 53 deletions(-) diff --git a/Core/Core.cpp b/Core/Core.cpp index c93cc683c6..1142b1781a 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -196,7 +196,7 @@ void UpdateRunLoop() { } void KeepScreenAwake() { -#ifdef _WIN32 +#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); #endif } diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index ad71b4ce75..38a823174a 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -17,7 +17,6 @@ #include "GPU/ge_constants.h" #include "GPU/GPUState.h" -#include "GPU/GLES/ShaderManagerGLES.h" #include "Common/ChunkFile.h" #include "Core/CoreParameter.h" diff --git a/UI/DisplayLayoutScreen.cpp b/UI/DisplayLayoutScreen.cpp index 7b9dfc2f7c..4e719533ed 100644 --- a/UI/DisplayLayoutScreen.cpp +++ b/UI/DisplayLayoutScreen.cpp @@ -28,7 +28,7 @@ #include "Core/Config.h" #include "Core/System.h" #include "DisplayLayoutEditor.h" -#include "GPU/GLES/FramebufferManagerGLES.h" +#include "GPU/Common/FramebufferCommon.h" static const int leftColumnWidth = 200; static const float orgRatio = 1.764706f; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 2f6b18213e..ce2886cd54 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -49,8 +49,10 @@ #include "Core/System.h" #include "GPU/GPUState.h" #include "GPU/GPUInterface.h" -#include "GPU/GLES/FramebufferManagerGLES.h" +#include "GPU/Common/FramebufferCommon.h" +#if !PPSSPP_PLATFORM(UWP) #include "GPU/Vulkan/DebugVisVulkan.h" +#endif #include "Core/HLE/sceCtrl.h" #include "Core/HLE/sceDisplay.h" #include "Core/HLE/sceSas.h" @@ -78,9 +80,6 @@ #if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) #include "Windows/MainWindow.h" #endif -#if !PPSSPP_PLATFORM(UWP) -#include "gfx/gl_common.h" -#endif #ifndef MOBILE_DEVICE static AVIDump avi; @@ -1212,9 +1211,11 @@ void EmuScreen::renderUI() { DrawFPS(draw2d, ctx->GetBounds()); } +#if !PPSSPP_PLATFORM(UWP) if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN && g_Config.bShowAllocatorDebug) { DrawAllocatorVis(ctx, gpu); } +#endif #ifdef USE_PROFILER if (g_Config.bShowFrameProfiler && !invalid_) { diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 6b63263d7d..c42427622c 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -54,7 +54,7 @@ #include "Core/Reporting.h" #include "android/jni/TestRunner.h" #include "GPU/GPUInterface.h" -#include "GPU/GLES/FramebufferManagerGLES.h" +#include "GPU/Common/FramebufferCommon.h" #if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) #pragma warning(disable:4091) // workaround bug in VS2015 headers diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index b7d1f40921..838205b571 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -313,6 +313,7 @@ + @@ -365,6 +366,7 @@ + diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters index fbb4d4939b..641d4feef0 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters @@ -160,6 +160,9 @@ Debugger + + Common + @@ -295,5 +298,8 @@ Debugger + + Common + \ No newline at end of file diff --git a/UWP/NativeUWP/NativeUWP.vcxproj b/UWP/NativeUWP/NativeUWP.vcxproj index 9db58ee9a8..599d491e0c 100644 --- a/UWP/NativeUWP/NativeUWP.vcxproj +++ b/UWP/NativeUWP/NativeUWP.vcxproj @@ -338,7 +338,6 @@ - @@ -1170,7 +1169,6 @@ - diff --git a/UWP/NativeUWP/NativeUWP.vcxproj.filters b/UWP/NativeUWP/NativeUWP.vcxproj.filters index d0abe95c90..6b58b4d5c1 100644 --- a/UWP/NativeUWP/NativeUWP.vcxproj.filters +++ b/UWP/NativeUWP/NativeUWP.vcxproj.filters @@ -451,9 +451,6 @@ data - - gfx - base @@ -725,8 +722,5 @@ data - - gfx - \ No newline at end of file diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 96d346b819..d2d805cde7 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -1,4 +1,4 @@ -#include "pch.h" +#include "pch.h" #include "PPSSPP_UWPMain.h" #include @@ -108,8 +108,7 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptrSetAllLogLevels(LogTypes::LDEBUG); diff --git a/ext/native/base/timeutil.cpp b/ext/native/base/timeutil.cpp index 6d10fc62f2..f48c87a276 100644 --- a/ext/native/base/timeutil.cpp +++ b/ext/native/base/timeutil.cpp @@ -7,8 +7,6 @@ #ifdef _WIN32 #include #else -#include "gfx/gl_common.h" -#include "gfx_es2/gpu_features.h" #include #include #endif @@ -41,25 +39,6 @@ uint64_t _frequency = 0; uint64_t _starttime = 0; double real_time_now() { -#ifdef __ANDROID__ - if (false && gl_extensions.EGL_NV_system_time) { - // This is needed to profile using PerfHUD on Tegra - if (_frequency == 0) { - _frequency = eglGetSystemTimeFrequencyNV(); - _starttime = eglGetSystemTimeNV(); - } - - uint64_t cur = eglGetSystemTimeNV(); - int64_t diff = cur - _starttime; - - return (double)diff / (double)_frequency; - } -#if 0 - // This clock is really "choppy" on Nexus 9! - struct timespec time; - clock_gettime(CLOCK_MONOTONIC_RAW, &time); - return time.tv_sec + time.tv_nsec / 1.0e9; -#else static time_t start; struct timeval tv; gettimeofday(&tv, NULL); @@ -68,18 +47,6 @@ double real_time_now() { } tv.tv_sec -= start; return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; -#endif - -#else - static time_t start; - struct timeval tv; - gettimeofday(&tv, NULL); - if (start == 0) { - start = tv.tv_sec; - } - tv.tv_sec -= start; - return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; -#endif } #endif diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 96dfe71302..552ba4b5c4 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -997,7 +997,7 @@ void GLQueueRunner::PerformReadback(const GLRStep &pass) { const GLuint format = GL_RGBA; const GLuint type = GL_UNSIGNED_BYTE; const int srcAlignment = 4; - int dstAlignment = DataFormatSizeInBytes(pass.readback.dstFormat); + int dstAlignment = (int)DataFormatSizeInBytes(pass.readback.dstFormat); int pixelStride = pass.readback.srcRect.w; // Apply the correct alignment. From 1a34f8833119c7b35a3b9d599b723ddd4c55c35a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 6 Feb 2018 19:41:00 +0100 Subject: [PATCH 116/291] Always use the bundled libzip to avoid compatibility issues. Should fix #10575 --- CMakeLists.txt | 123 ++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf9b4c99c0..3769806f31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -545,70 +545,65 @@ if (NOT MSVC) endif() -find_package(LibZip) -if(LIBZIP_FOUND) - add_definitions(-DSHARED_LIBZIP) -else() - add_library(libzip STATIC - ext/native/ext/libzip/zip.h - ext/native/ext/libzip/mkstemp.c - ext/native/ext/libzip/zip_add.c - ext/native/ext/libzip/zip_add_dir.c - ext/native/ext/libzip/zip_close.c - ext/native/ext/libzip/zip_delete.c - ext/native/ext/libzip/zip_dirent.c - ext/native/ext/libzip/zip_entry_free.c - ext/native/ext/libzip/zip_entry_new.c - ext/native/ext/libzip/zip_err_str.c - ext/native/ext/libzip/zip_error.c - ext/native/ext/libzip/zip_error_clear.c - ext/native/ext/libzip/zip_error_get.c - ext/native/ext/libzip/zip_error_get_sys_type.c - ext/native/ext/libzip/zip_error_strerror.c - ext/native/ext/libzip/zip_error_to_str.c - ext/native/ext/libzip/zip_fclose.c - ext/native/ext/libzip/zip_file_error_clear.c - ext/native/ext/libzip/zip_file_error_get.c - ext/native/ext/libzip/zip_file_get_offset.c - ext/native/ext/libzip/zip_file_strerror.c - ext/native/ext/libzip/zip_filerange_crc.c - ext/native/ext/libzip/zip_fopen.c - ext/native/ext/libzip/zip_fopen_index.c - ext/native/ext/libzip/zip_fread.c - ext/native/ext/libzip/zip_free.c - ext/native/ext/libzip/zip_get_archive_comment.c - ext/native/ext/libzip/zip_get_archive_flag.c - ext/native/ext/libzip/zip_get_file_comment.c - ext/native/ext/libzip/zip_get_name.c - ext/native/ext/libzip/zip_get_num_files.c - ext/native/ext/libzip/zip_memdup.c - ext/native/ext/libzip/zip_name_locate.c - ext/native/ext/libzip/zip_new.c - ext/native/ext/libzip/zip_open.c - ext/native/ext/libzip/zip_rename.c - ext/native/ext/libzip/zip_replace.c - ext/native/ext/libzip/zip_set_archive_comment.c - ext/native/ext/libzip/zip_set_archive_flag.c - ext/native/ext/libzip/zip_set_file_comment.c - ext/native/ext/libzip/zip_set_name.c - ext/native/ext/libzip/zip_source_buffer.c - ext/native/ext/libzip/zip_source_file.c - ext/native/ext/libzip/zip_source_filep.c - ext/native/ext/libzip/zip_source_free.c - ext/native/ext/libzip/zip_source_function.c - ext/native/ext/libzip/zip_source_zip.c - ext/native/ext/libzip/zip_stat.c - ext/native/ext/libzip/zip_stat_index.c - ext/native/ext/libzip/zip_stat_init.c - ext/native/ext/libzip/zip_strerror.c - ext/native/ext/libzip/zip_unchange.c - ext/native/ext/libzip/zip_unchange_all.c - ext/native/ext/libzip/zip_unchange_archive.c - ext/native/ext/libzip/zip_unchange_data.c) - target_link_libraries(libzip) - include_directories(ext/native/ext/libzip) - set(LIBZIP_LIBRARY libzip) -endif() +add_library(libzip STATIC + ext/native/ext/libzip/zip.h + ext/native/ext/libzip/mkstemp.c + ext/native/ext/libzip/zip_add.c + ext/native/ext/libzip/zip_add_dir.c + ext/native/ext/libzip/zip_close.c + ext/native/ext/libzip/zip_delete.c + ext/native/ext/libzip/zip_dirent.c + ext/native/ext/libzip/zip_entry_free.c + ext/native/ext/libzip/zip_entry_new.c + ext/native/ext/libzip/zip_err_str.c + ext/native/ext/libzip/zip_error.c + ext/native/ext/libzip/zip_error_clear.c + ext/native/ext/libzip/zip_error_get.c + ext/native/ext/libzip/zip_error_get_sys_type.c + ext/native/ext/libzip/zip_error_strerror.c + ext/native/ext/libzip/zip_error_to_str.c + ext/native/ext/libzip/zip_fclose.c + ext/native/ext/libzip/zip_file_error_clear.c + ext/native/ext/libzip/zip_file_error_get.c + ext/native/ext/libzip/zip_file_get_offset.c + ext/native/ext/libzip/zip_file_strerror.c + ext/native/ext/libzip/zip_filerange_crc.c + ext/native/ext/libzip/zip_fopen.c + ext/native/ext/libzip/zip_fopen_index.c + ext/native/ext/libzip/zip_fread.c + ext/native/ext/libzip/zip_free.c + ext/native/ext/libzip/zip_get_archive_comment.c + ext/native/ext/libzip/zip_get_archive_flag.c + ext/native/ext/libzip/zip_get_file_comment.c + ext/native/ext/libzip/zip_get_name.c + ext/native/ext/libzip/zip_get_num_files.c + ext/native/ext/libzip/zip_memdup.c + ext/native/ext/libzip/zip_name_locate.c + ext/native/ext/libzip/zip_new.c + ext/native/ext/libzip/zip_open.c + ext/native/ext/libzip/zip_rename.c + ext/native/ext/libzip/zip_replace.c + ext/native/ext/libzip/zip_set_archive_comment.c + ext/native/ext/libzip/zip_set_archive_flag.c + ext/native/ext/libzip/zip_set_file_comment.c + ext/native/ext/libzip/zip_set_name.c + ext/native/ext/libzip/zip_source_buffer.c + ext/native/ext/libzip/zip_source_file.c + ext/native/ext/libzip/zip_source_filep.c + ext/native/ext/libzip/zip_source_free.c + ext/native/ext/libzip/zip_source_function.c + ext/native/ext/libzip/zip_source_zip.c + ext/native/ext/libzip/zip_stat.c + ext/native/ext/libzip/zip_stat_index.c + ext/native/ext/libzip/zip_stat_init.c + ext/native/ext/libzip/zip_strerror.c + ext/native/ext/libzip/zip_unchange.c + ext/native/ext/libzip/zip_unchange_all.c + ext/native/ext/libzip/zip_unchange_archive.c + ext/native/ext/libzip/zip_unchange_data.c) +target_link_libraries(libzip) +include_directories(ext/native/ext/libzip) +set(LIBZIP_LIBRARY libzip) # FindPNG does a few things we don't want. So do it ourselves. Fixed to libpng17 find_path(PNG_PNG_INCLUDE_DIR NAMES "libpng17/png.h") From 59d6cc12f2c6713f62f11da54198854050b98fac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 7 Feb 2018 12:09:06 +0100 Subject: [PATCH 117/291] Add an option to use the system libzip, to please grumpy package maintainers. This reverts commit 1a34f8833119c7b35a3b9d599b723ddd4c55c35a. --- CMakeLists.txt | 124 ++++++++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 59 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3769806f31..a687b91ede 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,7 @@ option(SIMULATOR "Set to ON when targeting an x86 simulator of an ARM platform" # :: Options option(USE_FFMPEG "Build with FFMPEG support" ${USE_FFMPEG}) option(USE_SYSTEM_FFMPEG "Dynamically link against system FFMPEG" ${USE_SYSTEM_FFMPEG}) +option(USE_SYSTEM_LIBZIP "Dynamically link against system libzip" ${USE_SYSTEM_LIBZIP}) option(USE_WAYLAND_WSI "Set to ON to require Wayland support for Vulkan" ${USE_WAYLAND_WSI}) option(USE_ADDRESS_SANITIZER "Use Clang memory sanitizer" ${USE_ADDRESS_SANITIZER}) @@ -545,65 +546,70 @@ if (NOT MSVC) endif() -add_library(libzip STATIC - ext/native/ext/libzip/zip.h - ext/native/ext/libzip/mkstemp.c - ext/native/ext/libzip/zip_add.c - ext/native/ext/libzip/zip_add_dir.c - ext/native/ext/libzip/zip_close.c - ext/native/ext/libzip/zip_delete.c - ext/native/ext/libzip/zip_dirent.c - ext/native/ext/libzip/zip_entry_free.c - ext/native/ext/libzip/zip_entry_new.c - ext/native/ext/libzip/zip_err_str.c - ext/native/ext/libzip/zip_error.c - ext/native/ext/libzip/zip_error_clear.c - ext/native/ext/libzip/zip_error_get.c - ext/native/ext/libzip/zip_error_get_sys_type.c - ext/native/ext/libzip/zip_error_strerror.c - ext/native/ext/libzip/zip_error_to_str.c - ext/native/ext/libzip/zip_fclose.c - ext/native/ext/libzip/zip_file_error_clear.c - ext/native/ext/libzip/zip_file_error_get.c - ext/native/ext/libzip/zip_file_get_offset.c - ext/native/ext/libzip/zip_file_strerror.c - ext/native/ext/libzip/zip_filerange_crc.c - ext/native/ext/libzip/zip_fopen.c - ext/native/ext/libzip/zip_fopen_index.c - ext/native/ext/libzip/zip_fread.c - ext/native/ext/libzip/zip_free.c - ext/native/ext/libzip/zip_get_archive_comment.c - ext/native/ext/libzip/zip_get_archive_flag.c - ext/native/ext/libzip/zip_get_file_comment.c - ext/native/ext/libzip/zip_get_name.c - ext/native/ext/libzip/zip_get_num_files.c - ext/native/ext/libzip/zip_memdup.c - ext/native/ext/libzip/zip_name_locate.c - ext/native/ext/libzip/zip_new.c - ext/native/ext/libzip/zip_open.c - ext/native/ext/libzip/zip_rename.c - ext/native/ext/libzip/zip_replace.c - ext/native/ext/libzip/zip_set_archive_comment.c - ext/native/ext/libzip/zip_set_archive_flag.c - ext/native/ext/libzip/zip_set_file_comment.c - ext/native/ext/libzip/zip_set_name.c - ext/native/ext/libzip/zip_source_buffer.c - ext/native/ext/libzip/zip_source_file.c - ext/native/ext/libzip/zip_source_filep.c - ext/native/ext/libzip/zip_source_free.c - ext/native/ext/libzip/zip_source_function.c - ext/native/ext/libzip/zip_source_zip.c - ext/native/ext/libzip/zip_stat.c - ext/native/ext/libzip/zip_stat_index.c - ext/native/ext/libzip/zip_stat_init.c - ext/native/ext/libzip/zip_strerror.c - ext/native/ext/libzip/zip_unchange.c - ext/native/ext/libzip/zip_unchange_all.c - ext/native/ext/libzip/zip_unchange_archive.c - ext/native/ext/libzip/zip_unchange_data.c) -target_link_libraries(libzip) -include_directories(ext/native/ext/libzip) -set(LIBZIP_LIBRARY libzip) +find_package(LibZip) +if(LIBZIP_FOUND AND USE_SYSTEM_LIBZIP) + add_definitions(-DSHARED_LIBZIP) +else() + add_library(libzip STATIC + ext/native/ext/libzip/zip.h + ext/native/ext/libzip/mkstemp.c + ext/native/ext/libzip/zip_add.c + ext/native/ext/libzip/zip_add_dir.c + ext/native/ext/libzip/zip_close.c + ext/native/ext/libzip/zip_delete.c + ext/native/ext/libzip/zip_dirent.c + ext/native/ext/libzip/zip_entry_free.c + ext/native/ext/libzip/zip_entry_new.c + ext/native/ext/libzip/zip_err_str.c + ext/native/ext/libzip/zip_error.c + ext/native/ext/libzip/zip_error_clear.c + ext/native/ext/libzip/zip_error_get.c + ext/native/ext/libzip/zip_error_get_sys_type.c + ext/native/ext/libzip/zip_error_strerror.c + ext/native/ext/libzip/zip_error_to_str.c + ext/native/ext/libzip/zip_fclose.c + ext/native/ext/libzip/zip_file_error_clear.c + ext/native/ext/libzip/zip_file_error_get.c + ext/native/ext/libzip/zip_file_get_offset.c + ext/native/ext/libzip/zip_file_strerror.c + ext/native/ext/libzip/zip_filerange_crc.c + ext/native/ext/libzip/zip_fopen.c + ext/native/ext/libzip/zip_fopen_index.c + ext/native/ext/libzip/zip_fread.c + ext/native/ext/libzip/zip_free.c + ext/native/ext/libzip/zip_get_archive_comment.c + ext/native/ext/libzip/zip_get_archive_flag.c + ext/native/ext/libzip/zip_get_file_comment.c + ext/native/ext/libzip/zip_get_name.c + ext/native/ext/libzip/zip_get_num_files.c + ext/native/ext/libzip/zip_memdup.c + ext/native/ext/libzip/zip_name_locate.c + ext/native/ext/libzip/zip_new.c + ext/native/ext/libzip/zip_open.c + ext/native/ext/libzip/zip_rename.c + ext/native/ext/libzip/zip_replace.c + ext/native/ext/libzip/zip_set_archive_comment.c + ext/native/ext/libzip/zip_set_archive_flag.c + ext/native/ext/libzip/zip_set_file_comment.c + ext/native/ext/libzip/zip_set_name.c + ext/native/ext/libzip/zip_source_buffer.c + ext/native/ext/libzip/zip_source_file.c + ext/native/ext/libzip/zip_source_filep.c + ext/native/ext/libzip/zip_source_free.c + ext/native/ext/libzip/zip_source_function.c + ext/native/ext/libzip/zip_source_zip.c + ext/native/ext/libzip/zip_stat.c + ext/native/ext/libzip/zip_stat_index.c + ext/native/ext/libzip/zip_stat_init.c + ext/native/ext/libzip/zip_strerror.c + ext/native/ext/libzip/zip_unchange.c + ext/native/ext/libzip/zip_unchange_all.c + ext/native/ext/libzip/zip_unchange_archive.c + ext/native/ext/libzip/zip_unchange_data.c) + target_link_libraries(libzip) + include_directories(ext/native/ext/libzip) + set(LIBZIP_LIBRARY libzip) +endif() # FindPNG does a few things we don't want. So do it ourselves. Fixed to libpng17 find_path(PNG_PNG_INCLUDE_DIR NAMES "libpng17/png.h") From b3a09791b12bb5b5b8fb8c2b9bc54e59ea8fa9e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 7 Feb 2018 12:22:19 +0100 Subject: [PATCH 118/291] SDL: Fix emuthread management to exit cleanly without hanging. --- SDL/SDLMain.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index e6258fbe7d..e22036db57 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -432,6 +432,9 @@ static void EmuThreadStart(GraphicsContext *context) { static void EmuThreadStop() { emuThreadState = (int)EmuThreadState::QUIT_REQUESTED; +} + +static void EmuThreadJoin() { emuThread.join(); emuThread = std::thread(); } @@ -892,7 +895,14 @@ int main(int argc, char *argv[]) { framecount++; } - EmuThreadStop(); + if (useEmuThread) { + EmuThreadStop(); + while (emuThreadState != (int)EmuThreadState::STOPPED) { + // Need to keep eating frames to allow the EmuThread to exit correctly. + graphicsContext->ThreadFrame(); + } + EmuThreadJoin(); + } delete joystick; @@ -902,6 +912,7 @@ int main(int argc, char *argv[]) { graphicsContext->Shutdown(); graphicsContext->ThreadEnd(); graphicsContext->ShutdownFromRenderThread(); + NativeShutdown(); delete graphicsContext; From 7f30037e451b6521a74d55b09e8b5ca9dc76bcd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 7 Feb 2018 13:11:43 +0100 Subject: [PATCH 119/291] Android: Fix emuthread management to exit cleanly without hanging. Helps with task switching on Android. --- Windows/EmuThread.cpp | 5 +- android/jni/AndroidEGLContext.h | 3 + android/jni/AndroidGraphicsContext.h | 1 + android/jni/AndroidJavaGLContext.cpp | 1 + android/jni/AndroidJavaGLContext.h | 4 ++ android/jni/AndroidVulkanContext.h | 4 ++ android/jni/app-android.cpp | 65 +++++++++++++++++----- ext/native/thread/prioritizedworkqueue.cpp | 6 +- 8 files changed, 72 insertions(+), 17 deletions(-) diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index c48094bf79..2f839695eb 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -54,6 +54,9 @@ enum EmuThreadStatus : int { void EmuThreadFunc(); void RenderThreadFunc(); +// On most other platforms, we let the main thread become the render thread and +// start a separate emu thread from that, if needed. Should probably switch to that +// to make it the same on all platforms. void EmuThread_Start(bool separateRenderThread) { std::lock_guard guard(emuThreadLock); emuThread = std::thread(&EmuThreadFunc); @@ -218,7 +221,7 @@ void EmuThreadFunc() { if (g_Config.bBrowse) PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0); - Core_EnableStepping(FALSE); + Core_EnableStepping(false); while (GetUIState() != UISTATE_EXIT) { // We're here again, so the game quit. Restart Core_Run() which controls the UI. diff --git a/android/jni/AndroidEGLContext.h b/android/jni/AndroidEGLContext.h index fd86bc6cfe..2bc9d5341c 100644 --- a/android/jni/AndroidEGLContext.h +++ b/android/jni/AndroidEGLContext.h @@ -14,6 +14,9 @@ public: Draw::DrawContext *GetDrawContext() override { return draw_; } + bool Initialized() override { + return draw_ != nullptr; + } private: Draw::DrawContext *draw_; diff --git a/android/jni/AndroidGraphicsContext.h b/android/jni/AndroidGraphicsContext.h index 589cddc97d..50a213e68b 100644 --- a/android/jni/AndroidGraphicsContext.h +++ b/android/jni/AndroidGraphicsContext.h @@ -22,4 +22,5 @@ public: // This is different than the base class function since on // Android (EGL, Vulkan) we do have all this info on the render thread. virtual bool InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) = 0; + virtual bool Initialized() = 0; }; diff --git a/android/jni/AndroidJavaGLContext.cpp b/android/jni/AndroidJavaGLContext.cpp index c201c9fb10..4671cb7943 100644 --- a/android/jni/AndroidJavaGLContext.cpp +++ b/android/jni/AndroidJavaGLContext.cpp @@ -20,6 +20,7 @@ bool AndroidJavaEGLGraphicsContext::InitFromRenderThread(ANativeWindow *wnd, int void AndroidJavaEGLGraphicsContext::ShutdownFromRenderThread() { ILOG("AndroidJavaEGLGraphicsContext::Shutdown"); + renderManager_->WaitUntilQueueIdle(); renderManager_ = nullptr; // owned by draw_. delete draw_; draw_ = nullptr; diff --git a/android/jni/AndroidJavaGLContext.h b/android/jni/AndroidJavaGLContext.h index c6e11910e7..10b63c61bc 100644 --- a/android/jni/AndroidJavaGLContext.h +++ b/android/jni/AndroidJavaGLContext.h @@ -15,6 +15,10 @@ public: delete draw_; } + bool Initialized() override { + return draw_ != nullptr; + } + // This performs the actual initialization, bool InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) override; diff --git a/android/jni/AndroidVulkanContext.h b/android/jni/AndroidVulkanContext.h index e43041d3dc..2c65de11c3 100644 --- a/android/jni/AndroidVulkanContext.h +++ b/android/jni/AndroidVulkanContext.h @@ -22,6 +22,10 @@ public: Draw::DrawContext *GetDrawContext() override { return draw_; } + bool Initialized() override { + return draw_ != nullptr; + } + private: VulkanContext *g_Vulkan = nullptr; Draw::DrawContext *draw_ = nullptr; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 2d0731d711..d58b68dd92 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -171,6 +171,20 @@ static void EmuThreadFunc() { gJvm->AttachCurrentThread(&env, nullptr); setCurrentThreadName("Emu"); + ILOG("Entering emu thread"); + + // Wait for render loop to get started. + if (!graphicsContext || !graphicsContext->Initialized()) { + ILOG("Runloop: Waiting for displayInit..."); + while (!graphicsContext || !graphicsContext->Initialized()) { + sleep_ms(20); + } + } else { + ILOG("Runloop: Graphics context available! %p", graphicsContext); + } + NativeInitGraphics(graphicsContext); + + ILOG("Graphics initialized. Entering loop."); // There's no real requirement that NativeInit happen on this thread. // We just call the update/render loop here. @@ -179,18 +193,31 @@ static void EmuThreadFunc() { UpdateRunLoopAndroid(env); } emuThreadState = (int)EmuThreadState::STOPPED; + + NativeShutdownGraphics(); + gJvm->DetachCurrentThread(); + ILOG("Leaving emu thread"); } -static void EmuThreadStart(JNIEnv *env) { +static void EmuThreadStart() { + ILOG("EmuThreadStart"); emuThreadState = (int)EmuThreadState::START_REQUESTED; emuThread = std::thread(&EmuThreadFunc); } +// Call EmuThreadStop first, then keep running the GPU (or eat commands) +// as long as emuThreadState isn't STOPPED and/or there are still things queued up. +// Only after that, call EmuThreadJoin. static void EmuThreadStop() { + ILOG("EmuThreadStop - stopping..."); emuThreadState = (int)EmuThreadState::QUIT_REQUESTED; +} + +static void EmuThreadJoin() { emuThread.join(); emuThread = std::thread(); + ILOG("EmuThreadStop - joined."); } static void ProcessFrameCommands(JNIEnv *env); @@ -429,9 +456,8 @@ retry: if (useCPUThread) { ILOG("NativeApp.init() - launching emu thread"); - EmuThreadStart(env); + EmuThreadStart(); } - ILOG("NativeApp.init() -- end"); } extern "C" void Java_org_ppsspp_ppsspp_NativeApp_audioInit(JNIEnv *, jclass) { @@ -480,8 +506,13 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_pause(JNIEnv *, jclass) { } extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { - if (useCPUThread) + if (useCPUThread && graphicsContext) { EmuThreadStop(); + while (emuThreadState != (int)EmuThreadState::STOPPED) { + graphicsContext->ThreadFrame(); + } + EmuThreadJoin(); + } ILOG("NativeApp.shutdown() -- begin"); if (renderer_inited) { @@ -507,11 +538,28 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, // We should be running on the render thread here. std::string errorMessage; if (renderer_inited) { + // Would be really nice if we could get something on the GL thread immediately when shutting down... ILOG("NativeApp.displayInit() restoring"); graphicsContext->ThreadEnd(); + if (useCPUThread) { + EmuThreadStop(); + while (emuThreadState != (int)EmuThreadState::STOPPED) { + graphicsContext->ThreadFrame(); + } + EmuThreadJoin(); + } else { + NativeShutdownGraphics(); + } graphicsContext->ShutdownFromRenderThread(); + ILOG("Shut down both threads. Now let's bring it up again!"); + graphicsContext->InitFromRenderThread(nullptr, 0, 0, 0, 0); + if (useCPUThread) { + EmuThreadStart(); + } else { + NativeInitGraphics(graphicsContext); + } graphicsContext->ThreadStart(); ILOG("Restored."); } else { @@ -564,15 +612,6 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv } void UpdateRunLoopAndroid(JNIEnv *env) { - // Wait for render loop to get started. - if (!renderer_inited) { - ILOG("Runloop: Waiting for displayInit"); - while (!renderer_inited) { - sleep_ms(20); - } - NativeInitGraphics(graphicsContext); - } - NativeUpdate(); NativeRender(graphicsContext); diff --git a/ext/native/thread/prioritizedworkqueue.cpp b/ext/native/thread/prioritizedworkqueue.cpp index 1583738f40..35a1e94a62 100644 --- a/ext/native/thread/prioritizedworkqueue.cpp +++ b/ext/native/thread/prioritizedworkqueue.cpp @@ -112,7 +112,7 @@ PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() { static std::thread *workThread; static void threadfunc(PrioritizedWorkQueue *wq) { - setCurrentThreadName("PrioritizedWorkQueue"); + setCurrentThreadName("PrioQueue"); while (true) { PrioritizedWorkQueueItem *item = wq->Pop(); if (!item) { @@ -126,7 +126,7 @@ static void threadfunc(PrioritizedWorkQueue *wq) { } void ProcessWorkQueueOnThreadWhile(PrioritizedWorkQueue *wq) { - workThread = new std::thread(std::bind(&threadfunc, wq)); + workThread = new std::thread([=](){threadfunc(wq);}); } void StopProcessingWorkQueue(PrioritizedWorkQueue *wq) { @@ -135,5 +135,5 @@ void StopProcessingWorkQueue(PrioritizedWorkQueue *wq) { workThread->join(); delete workThread; } - workThread = 0; + workThread = nullptr; } From ae19c4813866b4da597a8f237a3b4ceb8824060c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 7 Feb 2018 15:52:19 +0100 Subject: [PATCH 120/291] Cleanup the Windows thread stuff to work like the other platforms. Not quite perfect yet. --- Core/Core.cpp | 6 +- SDL/SDLMain.cpp | 4 +- Windows/EmuThread.cpp | 217 +++++++++++++++++-------------- Windows/EmuThread.h | 6 +- Windows/GPU/WindowsGLContext.cpp | 2 - Windows/MainWindow.cpp | 11 +- Windows/main.cpp | 5 +- android/jni/app-android.cpp | 2 +- 8 files changed, 130 insertions(+), 123 deletions(-) diff --git a/Core/Core.cpp b/Core/Core.cpp index 1142b1781a..450ea97595 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -189,10 +189,7 @@ void UpdateRunLoop() { return; } NativeUpdate(); - - if (GetUIState() != UISTATE_EXIT) { - NativeRender(graphicsContext); - } + NativeRender(graphicsContext); } void KeepScreenAwake() { @@ -268,6 +265,7 @@ reswitch: if (GetUIState() != UISTATE_INGAME) { CoreStateProcessed(); if (GetUIState() == UISTATE_EXIT) { + UpdateRunLoop(); return; } Core_RunLoop(ctx); diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index e22036db57..e7d7faa15d 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -641,13 +641,13 @@ int main(int argc, char *argv[]) { useEmuThread = false; } + SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); + // Since we render from the main thread, there's nothing done here, but we call it to avoid confusion. if (!graphicsContext->InitFromRenderThread(&error_message)) { printf("Init from thread error: '%s'\n", error_message.c_str()); } - SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); - #ifdef MOBILE_DEVICE SDL_ShowCursor(SDL_DISABLE); #endif diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 2f839695eb..5b9d1faca5 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -24,102 +24,94 @@ #include "Core/Config.h" #include "thread/threadutil.h" -static std::mutex emuThreadLock; +enum class EmuThreadState { + DISABLED, + START_REQUESTED, + RUNNING, + QUIT_REQUESTED, + STOPPED, +}; + static std::thread emuThread; -static std::atomic emuThreadState; +static std::atomic emuThreadState((int)EmuThreadState::DISABLED); -static std::mutex renderThreadLock; -static std::thread renderThread; -static std::atomic renderThreadReady; - -static bool useRenderThread; -static bool renderThreadFailed; -static bool renderThreadSucceeded; +static std::thread mainThread; +static bool useEmuThread; static std::string g_error_message; +static bool g_inLoop; extern std::vector GetWideCmdLine(); class GraphicsContext; - static GraphicsContext *g_graphicsContext; -enum EmuThreadStatus : int { - THREAD_NONE = 0, - THREAD_INIT, - THREAD_CORE_LOOP, - THREAD_SHUTDOWN, - THREAD_END, -}; +void EmuThreadFunc(GraphicsContext *graphicsContext); +void MainThreadFunc(); -void EmuThreadFunc(); -void RenderThreadFunc(); - -// On most other platforms, we let the main thread become the render thread and +// On most other platforms, we let the "main" thread become the render thread and // start a separate emu thread from that, if needed. Should probably switch to that // to make it the same on all platforms. -void EmuThread_Start(bool separateRenderThread) { - std::lock_guard guard(emuThreadLock); - emuThread = std::thread(&EmuThreadFunc); - useRenderThread = separateRenderThread; - if (useRenderThread) { - renderThread = std::thread(&RenderThreadFunc); - } +void MainThread_Start(bool separateEmuThread) { + useEmuThread = separateEmuThread; + mainThread = std::thread(&MainThreadFunc); } -void EmuThread_Stop() { +void MainThread_Stop() { // Already stopped? - { - std::lock_guard guard(emuThreadLock); - if (emuThreadState == THREAD_END) - return; - } - UpdateUIState(UISTATE_EXIT); - Core_Stop(); - Core_WaitInactive(800); - emuThread.join(); - if (useRenderThread) { - renderThread.join(); - } - - PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_UPDATE_UI, 0, 0); + mainThread.join(); } -bool EmuThread_Ready() { - return emuThreadState == THREAD_CORE_LOOP; +bool MainThread_Ready() { + return g_inLoop; } -void RenderThreadFunc() { - setCurrentThreadName("Render"); - renderThreadFailed = false; - renderThreadSucceeded = false; - while (!g_graphicsContext) { - sleep_ms(10); - continue; - } - - std::string error_message; - if (!g_graphicsContext->InitFromRenderThread(&error_message)) { - g_error_message = error_message; - renderThreadFailed = true; - return; - } else { - renderThreadSucceeded = true; - } - - g_graphicsContext->ThreadStart(); - while (g_graphicsContext->ThreadFrame()) { - continue; - } - g_graphicsContext->ThreadEnd(); - g_graphicsContext->ShutdownFromRenderThread(); -} - -void EmuThreadFunc() { - emuThreadState = THREAD_INIT; - +static void EmuThreadFunc(GraphicsContext *graphicsContext) { setCurrentThreadName("Emu"); + // There's no real requirement that NativeInit happen on this thread. + // We just call the update/render loop here. + emuThreadState = (int)EmuThreadState::RUNNING; + + NativeInitGraphics(graphicsContext); + + while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) { + // We're here again, so the game quit. Restart Core_Run() which controls the UI. + // This way they can load a new game. + if (!Core_IsActive()) + UpdateUIState(UISTATE_MENU); + Core_Run(g_graphicsContext); + } + + emuThreadState = (int)EmuThreadState::STOPPED; + + NativeShutdownGraphics(); +} + +static void EmuThreadStart(GraphicsContext *graphicsContext) { + emuThreadState = (int)EmuThreadState::START_REQUESTED; + emuThread = std::thread(&EmuThreadFunc, graphicsContext); +} + +static void EmuThreadStop() { + emuThreadState = (int)EmuThreadState::QUIT_REQUESTED; +} + +static void EmuThreadJoin() { + emuThread.join(); + emuThread = std::thread(); + ILOG("EmuThreadJoin - joined"); +} + +void MainThreadFunc() { + if (useEmuThread) { + // We'll start up a separate thread we'll call Emu + setCurrentThreadName("Render"); + } else { + // This is both Emu and Render. + setCurrentThreadName("Emu"); + } + host = new WindowsHost(MainWindow::GetHInstance(), MainWindow::GetHWND(), MainWindow::GetDisplayHWND()); host->SetWindowTitle(nullptr); @@ -142,18 +134,8 @@ void EmuThreadFunc() { bool success = host->InitGraphics(&error_string, &g_graphicsContext); if (success) { - if (!useRenderThread) { - // This is also the render thread. - success = g_graphicsContext->InitFromRenderThread(&error_string); - } else { - while (!renderThreadFailed && !renderThreadSucceeded) { - sleep_ms(10); - } - success = renderThreadSucceeded; - if (!success) { - error_string = g_error_message; - } - } + // Main thread is the render thread. + success = g_graphicsContext->InitFromRenderThread(&error_string); } if (!success) { @@ -205,8 +187,12 @@ void EmuThreadFunc() { exit(1); } - NativeInitGraphics(g_graphicsContext); - NativeResized(); + GraphicsContext *graphicsContext = g_graphicsContext; + + if (!useEmuThread) { + NativeInitGraphics(graphicsContext); + NativeResized(); + } INFO_LOG(BOOT, "Done."); _dbg_update_(); @@ -216,30 +202,59 @@ void EmuThreadFunc() { goto shutdown; } - emuThreadState = THREAD_CORE_LOOP; + g_inLoop = true; + + if (useEmuThread) { + EmuThreadStart(graphicsContext); + } + graphicsContext->ThreadStart(); if (g_Config.bBrowse) PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0); Core_EnableStepping(false); - while (GetUIState() != UISTATE_EXIT) { - // We're here again, so the game quit. Restart Core_Run() which controls the UI. - // This way they can load a new game. - if (!Core_IsActive()) - UpdateUIState(UISTATE_MENU); - Core_Run(g_graphicsContext); + if (useEmuThread) { + while (emuThreadState != (int)EmuThreadState::DISABLED) { + graphicsContext->ThreadFrame(); + if (GetUIState() == UISTATE_EXIT) { + break; + } + } + } else { + while (GetUIState() != UISTATE_EXIT) { + // We're here again, so the game quit. Restart Core_Run() which controls the UI. + // This way they can load a new game. + if (!Core_IsActive()) + UpdateUIState(UISTATE_MENU); + Core_Run(g_graphicsContext); + } + } + Core_Stop(); + Core_WaitInactive(800); + + g_inLoop = false; + + if (useEmuThread) { + EmuThreadStop(); + while (emuThreadState != (int)EmuThreadState::STOPPED) { + // Need to keep eating frames to allow the EmuThread to exit correctly. + graphicsContext->ThreadFrame(); + } + EmuThreadJoin(); } shutdown: - emuThreadState = THREAD_SHUTDOWN; - NativeShutdownGraphics(); - if (!useRenderThread) - g_graphicsContext->ShutdownFromRenderThread(); + if (!useEmuThread) { + NativeShutdownGraphics(); + } + + g_graphicsContext->ThreadEnd(); + g_graphicsContext->ShutdownFromRenderThread(); // NativeShutdown deletes the graphics context through host->ShutdownGraphics(). NativeShutdown(); - emuThreadState = THREAD_END; -} + PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_UPDATE_UI, 0, 0); +} diff --git a/Windows/EmuThread.h b/Windows/EmuThread.h index d232fefb14..bc04bc3f06 100644 --- a/Windows/EmuThread.h +++ b/Windows/EmuThread.h @@ -17,6 +17,6 @@ #pragma once -void EmuThread_Start(bool separateRenderThread); -void EmuThread_Stop(); -bool EmuThread_Ready(); +void MainThread_Start(bool separateRenderThread); +void MainThread_Stop(); +bool MainThread_Ready(); diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 53cf6580f8..ac48df35fd 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -386,8 +386,6 @@ void WindowsGLContext::SwapInterval(int interval) { } void WindowsGLContext::Shutdown() { - if (renderManager_) - renderManager_->StopThread(); glslang::FinalizeProcess(); } diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index a3c45e3567..331b6a8c1d 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -795,7 +795,7 @@ namespace MainWindow case WM_COMMAND: { - if (!EmuThread_Ready()) + if (!MainThread_Ready()) return DefWindowProc(hWnd, message, wParam, lParam); MainWindowMenu_Process(hWnd, wParam); @@ -844,7 +844,7 @@ namespace MainWindow case WM_DROPFILES: { - if (!EmuThread_Ready()) + if (!MainThread_Ready()) return DefWindowProc(hWnd, message, wParam, lParam); HDROP hdrop = (HDROP)wParam; @@ -866,9 +866,8 @@ namespace MainWindow case WM_CLOSE: InputDevice::StopPolling(); - EmuThread_Stop(); + MainThread_Stop(); WindowsRawInput::Shutdown(); - return DefWindowProc(hWnd,message,wParam,lParam); case WM_DESTROY: @@ -914,10 +913,10 @@ namespace MainWindow case WM_USER_RESTART_EMUTHREAD: NativeSetRestarting(); InputDevice::StopPolling(); - EmuThread_Stop(); + MainThread_Stop(); coreState = CORE_POWERUP; ResetUIState(); - EmuThread_Start(false); + MainThread_Start(false); InputDevice::BeginPolling(); break; diff --git a/Windows/main.cpp b/Windows/main.cpp index 66c09110ba..03dbf883cb 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -532,7 +532,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin // Emu thread (and render thread, if any) is always running! // Only OpenGL uses an externally managed render thread (due to GL's single-threaded context design). Vulkan // manages its own render thread. - EmuThread_Start(g_Config.iGPUBackend == (int)GPUBackend::OPENGL); + MainThread_Start(g_Config.iGPUBackend == (int)GPUBackend::OPENGL); InputDevice::BeginPolling(); HACCEL hAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_ACCELS); @@ -586,9 +586,6 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin InputDevice::StopPolling(); - // The emuthread calls NativeShutdown when shutting down. - EmuThread_Stop(); - MainWindow::DestroyDebugWindows(); DialogManager::DestroyAll(); timeEndPeriod(1); diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index d58b68dd92..d62e0f29e4 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -217,7 +217,7 @@ static void EmuThreadStop() { static void EmuThreadJoin() { emuThread.join(); emuThread = std::thread(); - ILOG("EmuThreadStop - joined."); + ILOG("EmuThreadJoin - joined"); } static void ProcessFrameCommands(JNIEnv *env); From 87cc586c0827fe60748b97a10a08b3988a38b3fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 7 Feb 2018 16:43:49 +0100 Subject: [PATCH 121/291] Qt: Fix emuthread management to exit cleanly without hanging --- Qt/QtMain.cpp | 14 ++++++++++---- Qt/QtMain.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 16f3292a84..74d8be6b2d 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -191,7 +191,6 @@ static int mainInternal(QApplication &a) { } void MainUI::EmuThreadFunc() { - ILOG("In emu thread"); setCurrentThreadName("Emu"); // There's no real requirement that NativeInit happen on this thread, though it can't hurt... @@ -204,12 +203,11 @@ void MainUI::EmuThreadFunc() { SDL_PumpEvents(); #endif updateAccelerometer(); - time_update(); UpdateRunLoop(); } - NativeShutdownGraphics(); - emuThreadState = (int)EmuThreadState::STOPPED; + + NativeShutdownGraphics(); } void MainUI::EmuThreadStart() { @@ -219,6 +217,9 @@ void MainUI::EmuThreadStart() { void MainUI::EmuThreadStop() { emuThreadState = (int)EmuThreadState::QUIT_REQUESTED; +} + +void MainUI::EmuThreadJoin() { emuThread.join(); emuThread = std::thread(); } @@ -246,6 +247,11 @@ MainUI::~MainUI() if (emuThreadState != (int)EmuThreadState::DISABLED) { ILOG("EmuThreadStop"); EmuThreadStop(); + while (emuThreadState != (int)EmuThreadState::STOPPED) { + // Need to keep eating frames to allow the EmuThread to exit correctly. + graphicsContext->ThreadFrame(); + } + EmuThreadJoin(); } #if defined(MOBILE_DEVICE) delete acc; diff --git a/Qt/QtMain.h b/Qt/QtMain.h index fc04446b00..cc39d5802b 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -120,6 +120,7 @@ protected: void EmuThreadFunc(); void EmuThreadStart(); void EmuThreadStop(); + void EmuThreadJoin(); private: QtDummyGraphicsContext *graphicsContext; From b3f4a923ca7da656ad68cf10ba4ef10aa12b1e6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 7 Feb 2018 16:54:39 +0100 Subject: [PATCH 122/291] GLES: Fix minor memory leak --- GPU/GLES/DrawEngineGLES.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 405b929e63..5988ee5fa1 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -192,6 +192,8 @@ void DrawEngineGLES::DestroyDeviceObjects() { if (softwareInputLayout_) render_->DeleteInputLayout(softwareInputLayout_); softwareInputLayout_ = nullptr; + + ClearInputLayoutMap(); } void DrawEngineGLES::ClearInputLayoutMap() { From ce16547854be3ee2013f9ec468587d9cb0f2df15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 7 Feb 2018 19:49:31 +0100 Subject: [PATCH 123/291] GL render manager: Fix bug when setting texture sampler if the wrong GL texture slot is active. Will likely help #10583 --- GPU/GLES/FramebufferManagerGLES.cpp | 6 +++--- GPU/GLES/StateMappingGLES.cpp | 2 +- GPU/GLES/TextureCacheGLES.cpp | 8 ++++---- ext/native/thin3d/GLQueueRunner.cpp | 18 +++++++++++++++--- ext/native/thin3d/GLQueueRunner.h | 2 ++ ext/native/thin3d/GLRenderManager.h | 6 ++++-- ext/native/thin3d/thin3d_gl.cpp | 2 +- 7 files changed, 30 insertions(+), 14 deletions(-) diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 9754e2a185..fc0e04ff12 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -423,11 +423,11 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float pos[i * 3 + 1] = pos[i * 3 + 1] * invDestH - 1.0f; } - // Upscaling postshaders doesn't look well with linear + // Upscaling postshaders don't look well with linear if (flags & DRAWTEX_LINEAR) { - render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); + render_->SetTextureSampler(0, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); } else { - render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); + render_->SetTextureSampler(0, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); } Simple2DVertex verts[4]; diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index b3c25e01c2..5a5fc1f071 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -180,7 +180,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) { // TODO: If the device doesn't support blit, this will corrupt the currently applied texture. framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY); // If we are rendering at a higher resolution, linear is probably best for the dest color. - renderManager->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); + renderManager->SetTextureSampler(1, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); fboTexBound_ = true; fboTexNeedBind_ = false; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 59eb3184c1..d16f14f372 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -151,11 +151,11 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { minLod = 0.0f; maxLod = 0.0f; } - render_->SetTextureLod(minLod, maxLod, lodBias); + render_->SetTextureLod(0, minLod, maxLod, lodBias); } float aniso = 0.0f; - render_->SetTextureSampler(sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); + render_->SetTextureSampler(0, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); } void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight) { @@ -170,7 +170,7 @@ void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferH minFilt &= 1; // framebuffers can't mipmap. float aniso = 0.0f; - render_->SetTextureSampler(sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); + render_->SetTextureSampler(0, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); // Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case. // This happens whether we have OES_texture_npot or not. @@ -447,7 +447,7 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram framebufferManagerGL_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY); render_->BindTexture(3, clutTexture); - render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); + render_->SetTextureSampler(3, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); shaderApply.Shade(render_); diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 552ba4b5c4..466a6d958a 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -816,7 +816,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { break; case GLRRenderCommand::TEXTURESAMPLER: { - GLRTexture *tex = curTex[activeSlot]; + GLint slot = c.textureSampler.slot; + if (slot != activeSlot) { + glActiveTexture(GL_TEXTURE0 + slot); + activeSlot = slot; + } + GLRTexture *tex = curTex[slot]; if (!tex) { break; } @@ -846,7 +851,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } case GLRRenderCommand::TEXTURELOD: { - GLRTexture *tex = curTex[activeSlot]; + GLint slot = c.textureSampler.slot; + if (slot != activeSlot) { + glActiveTexture(GL_TEXTURE0 + slot); + activeSlot = slot; + } + GLRTexture *tex = curTex[slot]; if (!tex) { break; } @@ -900,8 +910,10 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } } - if (activeSlot != 0) + if (activeSlot != 0) { glActiveTexture(GL_TEXTURE0); + activeSlot = 0; // doesn't matter, just nice. + } // Wipe out the current state. glBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 6043e80c94..63a17503c4 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -152,6 +152,7 @@ struct GLRRenderData { size_t offset; } bindVertexBuffer; struct { + int slot; GLenum wrapS; GLenum wrapT; GLenum magFilter; @@ -159,6 +160,7 @@ struct GLRRenderData { float anisotropy; } textureSampler; struct { + int slot; float minLod; float maxLod; float lodBias; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 670ecd72f7..4ef204d558 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -567,9 +567,10 @@ public: } // Modifies the current texture as per GL specs, not global state. - void SetTextureSampler(GLenum wrapS, GLenum wrapT, GLenum magFilter, GLenum minFilter, float anisotropy) { + void SetTextureSampler(int slot, GLenum wrapS, GLenum wrapT, GLenum magFilter, GLenum minFilter, float anisotropy) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::TEXTURESAMPLER }; + data.textureSampler.slot = slot; data.textureSampler.wrapS = wrapS; data.textureSampler.wrapT = wrapT; data.textureSampler.magFilter = magFilter; @@ -578,9 +579,10 @@ public: curRenderStep_->commands.push_back(data); } - void SetTextureLod(float minLod, float maxLod, float lodBias) { + void SetTextureLod(int slot, float minLod, float maxLod, float lodBias) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::TEXTURELOD}; + data.textureLod.slot = slot; data.textureLod.minLod = minLod; data.textureLod.maxLod = maxLod; data.textureLod.lodBias = lodBias; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 6d81a98c6e..6d5513de29 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -921,7 +921,7 @@ void OpenGLContext::ApplySamplers() { } GLenum magFilt = samp->magFilt; GLenum minFilt = tex->HasMips() ? samp->mipMinFilt : samp->minFilt; - renderManager_.SetTextureSampler(wrapS, wrapT, magFilt, minFilt, 0.0f); + renderManager_.SetTextureSampler(i, wrapS, wrapT, magFilt, minFilt, 0.0f); } } } From 8ee426ff74916b9637411b9cd66b1994f701b25b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 00:23:48 +0100 Subject: [PATCH 124/291] Get rid of an unused codepath (gl rendering is now always threaded) --- Windows/GPU/WindowsGLContext.cpp | 3 +- Windows/MainThread.h | 1 + ext/native/thin3d/GLRenderManager.cpp | 70 ++++++++------------------- ext/native/thin3d/GLRenderManager.h | 17 ++----- 4 files changed, 28 insertions(+), 63 deletions(-) create mode 100644 Windows/MainThread.h diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index ac48df35fd..7962d3a817 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -35,7 +35,8 @@ #include "Windows/GPU/WindowsGLContext.h" void WindowsGLContext::SwapBuffers() { - renderManager_->Swap(); + // We no longer call RenderManager::Swap here, it's handled by the render thread, which + // we're not on here. // Used during fullscreen switching to prevent rendering. if (pauseRequested) { diff --git a/Windows/MainThread.h b/Windows/MainThread.h new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/Windows/MainThread.h @@ -0,0 +1 @@ +#pragma once diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index e4a4ab23ae..b6e049a1f6 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -45,11 +45,6 @@ GLRenderManager::GLRenderManager() { for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { } - - if (!useThread_) { - // The main thread is also the render thread. - ThreadStart(); - } } GLRenderManager::~GLRenderManager() { @@ -58,12 +53,7 @@ GLRenderManager::~GLRenderManager() { } // Was anything deleted during shutdown? deleter_.Perform(); - // _assert_(deleter_.IsEmpty()); - - if (!useThread_) { - // The main thread is also the render thread. - ThreadEnd(); - } + _assert_(deleter_.IsEmpty()); } void GLRenderManager::ThreadStart() { @@ -143,7 +133,7 @@ bool GLRenderManager::ThreadFrame() { void GLRenderManager::StopThread() { // Since we don't control the thread directly, this will only pause the thread. - if (useThread_ && run_) { + if (run_) { run_ = false; for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { auto &frameData = frameData_[i]; @@ -170,6 +160,7 @@ void GLRenderManager::StopThread() { // when we restart... for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { auto &frameData = frameData_[i]; + std::unique_lock lock(frameData.push_mutex); if (frameData.readyForRun || frameData.steps.size() != 0) { Crash(); } @@ -181,7 +172,6 @@ void GLRenderManager::StopThread() { frameData.steps.clear(); frameData.initSteps.clear(); - std::unique_lock lock(frameData.push_mutex); while (!frameData.readyForFence) { VLOG("PUSH: Waiting for frame[%d].readyForFence = 1 (stop)", i); frameData.push_condVar.wait(lock); @@ -330,7 +320,7 @@ void GLRenderManager::BeginFrame() { FrameData &frameData = frameData_[curFrame]; // Make sure the very last command buffer from the frame before the previous has been fully executed. - if (useThread_) { + { std::unique_lock lock(frameData.push_mutex); while (!frameData.readyForFence) { VLOG("PUSH: Waiting for frame[%d].readyForFence = 1", curFrame); @@ -342,10 +332,7 @@ void GLRenderManager::BeginFrame() { VLOG("PUSH: Fencing %d", curFrame); - - // vkWaitForFences(device, 1, &frameData.fence, true, UINT64_MAX); - // vkResetFences(device, 1, &frameData.fence); - // glFenceSync(...) + // glFenceSync(&frameData.fence...) // Must be after the fence - this performs deletes. VLOG("PUSH: BeginFrame %d", curFrame); @@ -363,14 +350,7 @@ void GLRenderManager::Finish() { curRenderStep_ = nullptr; int curFrame = GetCurFrame(); FrameData &frameData = frameData_[curFrame]; - if (!useThread_) { - frameData.steps = std::move(steps_); - steps_.clear(); - frameData.initSteps = std::move(initSteps_); - initSteps_.clear(); - frameData.type = GLRRunType::END; - Run(curFrame); - } else { + { std::unique_lock lock(frameData.pull_mutex); VLOG("PUSH: Frame[%d].readyForRun = true", curFrame); frameData.steps = std::move(steps_); @@ -398,6 +378,7 @@ void GLRenderManager::BeginSubmitFrame(int frame) { } } +// Render thread void GLRenderManager::Submit(int frame, bool triggerFence) { FrameData &frameData = frameData_[frame]; @@ -409,7 +390,7 @@ void GLRenderManager::Submit(int frame, bool triggerFence) { // ideally we'd like to wait a frame or two. frameData.deleter.Perform(); - if (useThread_ && triggerFence) { + if (triggerFence) { VLOG("PULL: Frame %d.readyForFence = true", frame); std::unique_lock lock(frameData.push_mutex); @@ -420,6 +401,7 @@ void GLRenderManager::Submit(int frame, bool triggerFence) { } } +// Render thread void GLRenderManager::EndSubmitFrame(int frame) { FrameData &frameData = frameData_[frame]; frameData.hasBegun = false; @@ -435,6 +417,7 @@ void GLRenderManager::EndSubmitFrame(int frame) { } } +// Render thread void GLRenderManager::Run(int frame) { BeginSubmitFrame(frame); @@ -472,14 +455,7 @@ void GLRenderManager::FlushSync() { // TODO: Reset curRenderStep_? int curFrame = curFrame_; FrameData &frameData = frameData_[curFrame]; - if (!useThread_) { - frameData.initSteps = std::move(initSteps_); - initSteps_.clear(); - frameData.steps = std::move(steps_); - steps_.clear(); - frameData.type = GLRRunType::SYNC; - Run(curFrame); - } else { + { std::unique_lock lock(frameData.pull_mutex); VLOG("PUSH: Frame[%d].readyForRun = true (sync)", curFrame); frameData.initSteps = std::move(initSteps_); @@ -491,8 +467,7 @@ void GLRenderManager::FlushSync() { frameData.type = GLRRunType::SYNC; frameData.pull_condVar.notify_all(); } - - if (useThread_) { + { std::unique_lock lock(frameData.push_mutex); // Wait for the flush to be hit, since we're syncing. while (!frameData.readyForFence) { @@ -504,19 +479,20 @@ void GLRenderManager::FlushSync() { } } +// Render thread void GLRenderManager::EndSyncFrame(int frame) { FrameData &frameData = frameData_[frame]; Submit(frame, false); - // This is brutal! Should probably wait for a fence instead, not that it'll matter much since we'll - // still stall everything. - glFinish(); + // glFinish is not actually necessary here, and won't be until we start using + // glBufferStorage. Then we need to use fences. + // glFinish(); // At this point we can resume filling the command buffers for the current frame since // we know the device is idle - and thus all previously enqueued command buffers have been processed. // No need to switch to the next frame number. - if (useThread_) { + { std::unique_lock lock(frameData.push_mutex); frameData.readyForFence = true; frameData.readyForSubmit = true; @@ -533,11 +509,6 @@ void GLRenderManager::Wipe() { } void GLRenderManager::WaitUntilQueueIdle() { - if (!useThread_) { - // Must be idle, nothing to do. - return; - } - // Just wait for all frames to be ready. for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { FrameData &frameData = frameData_[i]; @@ -563,16 +534,15 @@ GLPushBuffer::~GLPushBuffer() { void GLPushBuffer::Map() { assert(!writePtr_); // TODO: Even a good old glMapBuffer could actually work well here. - // VkResult res = vkMapMemory(device_, buffers_[buf_].deviceMemory, 0, size_, 0, (void **)(&writePtr_)); writePtr_ = buffers_[buf_].deviceMemory; assert(writePtr_); } void GLPushBuffer::Unmap() { assert(writePtr_); - // Here we should simply upload everything to the buffers. - // Might be worth trying with size_ instead of offset_, so the driver can replace the whole buffer. - // At least if it's close. + // Here we simply upload the data to the last buffer. + // Might be worth trying with size_ instead of offset_, so the driver can replace + // the whole buffer. At least if it's close. render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].deviceMemory, false); writePtr_ = nullptr; } diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 4ef204d558..b658a116cf 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -663,12 +663,6 @@ public: swapFunction_ = swapFunction; } - void Swap() { - if (!useThread_ && swapFunction_) { - swapFunction_(); - } - } - void StopThread(); bool SawOutOfMemory() { @@ -738,8 +732,6 @@ private: GLDeleter deleter_; - bool useThread_ = true; - int curFrame_ = 0; std::function swapFunction_; @@ -748,10 +740,11 @@ private: int targetHeight_ = 0; }; - -// Similar to VulkanPushBuffer but uses really stupid tactics - collect all the data in RAM then do a big -// memcpy/buffer upload at the end. This can however be optimized with glBufferStorage on chips that support that -// for massive boosts. +// Similar to VulkanPushBuffer but is currently less efficient - it collects all the data in +// RAM then does a big memcpy/buffer upload at the end of the frame. This is at least a lot +// faster than the hundreds of buffer uploads or memory array buffers we used before. +// On modern GL we could avoid the copy using glBufferStorage but not sure it's worth the +// trouble. class GLPushBuffer { public: struct BufInfo { From 481134bfe9ccb3098bbbe44e45a23a9afb3dc1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 00:40:55 +0100 Subject: [PATCH 125/291] Another go at the deleter problem. Still not feeling 100% good about how this works.. but it does seem to work fine. --- ext/native/thin3d/GLRenderManager.cpp | 19 +++++++++---------- ext/native/thin3d/GLRenderManager.h | 4 +--- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index b6e049a1f6..d5ee6be8b3 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -13,7 +13,6 @@ #endif void GLDeleter::Perform() { - deleterMutex_.lock(); for (auto shader : shaders) { delete shader; } @@ -38,7 +37,6 @@ void GLDeleter::Perform() { delete framebuffer; } framebuffers.clear(); - deleterMutex_.unlock(); } GLRenderManager::GLRenderManager() { @@ -50,6 +48,7 @@ GLRenderManager::GLRenderManager() { GLRenderManager::~GLRenderManager() { for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { _assert_(frameData_[i].deleter.IsEmpty()); + _assert_(frameData_[i].deleter_prev.IsEmpty()); } // Was anything deleted during shutdown? deleter_.Perform(); @@ -72,6 +71,7 @@ void GLRenderManager::ThreadEnd() { // Good point to run all the deleters to get rid of leftover objects. for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { frameData_[i].deleter.Perform(); + frameData_[i].deleter_prev.Perform(); for (int j = 0; j < (int)frameData_[i].steps.size(); j++) { delete frameData_[i].steps[j]; } @@ -110,8 +110,10 @@ bool GLRenderManager::ThreadFrame() { // This means we're out of frames to render and run_ is false, so bail. return false; } - VLOG("PULL: frame[%d].readyForRun = false", threadFrame_); + VLOG("PULL: Setting frame[%d].readyForRun = false", threadFrame_); frameData.readyForRun = false; + frameData.deleter_prev.Perform(); + frameData.deleter_prev.Take(frameData.deleter); // Previously we had a quick exit here that avoided calling Run() if run_ was suddenly false, // but that created a race condition where frames could end up not finished properly on resize etc. @@ -352,17 +354,18 @@ void GLRenderManager::Finish() { FrameData &frameData = frameData_[curFrame]; { std::unique_lock lock(frameData.pull_mutex); - VLOG("PUSH: Frame[%d].readyForRun = true", curFrame); + VLOG("PUSH: Frame[%d].readyForRun = true, notifying pull", curFrame); frameData.steps = std::move(steps_); steps_.clear(); frameData.initSteps = std::move(initSteps_); initSteps_.clear(); frameData.readyForRun = true; frameData.type = GLRRunType::END; - frameData.pull_condVar.notify_all(); + frameData_[curFrame_].deleter.Take(deleter_); } - frameData_[curFrame_].deleter.Take(deleter_); + // Notify calls do not in fact need to be done with the mutex locked. + frameData.pull_condVar.notify_all(); curFrame_++; if (curFrame_ >= MAX_INFLIGHT_FRAMES) @@ -386,10 +389,6 @@ void GLRenderManager::Submit(int frame, bool triggerFence) { // When !triggerFence, we notify after syncing with Vulkan. - // Putting deletes here is safe but only because OpenGL has its own delete handling.. - // ideally we'd like to wait a frame or two. - frameData.deleter.Perform(); - if (triggerFence) { VLOG("PULL: Frame %d.readyForFence = true", frame); diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index b658a116cf..8b489c197d 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -157,7 +157,6 @@ public: return shaders.empty() && programs.empty() && buffers.empty() && textures.empty() && inputLayouts.empty() && framebuffers.empty(); } void Take(GLDeleter &other) { - deleterMutex_.lock(); _assert_msg_(G3D, IsEmpty(), "Deleter already has stuff"); shaders = std::move(other.shaders); programs = std::move(other.programs); @@ -171,7 +170,6 @@ public: other.textures.clear(); other.inputLayouts.clear(); other.framebuffers.clear(); - deleterMutex_.unlock(); } std::vector shaders; @@ -180,7 +178,6 @@ public: std::vector textures; std::vector inputLayouts; std::vector framebuffers; - std::mutex deleterMutex_; }; class GLRInputLayout { @@ -706,6 +703,7 @@ private: uint32_t curSwapchainImage = -1; GLDeleter deleter; + GLDeleter deleter_prev; std::set activePushBuffers; }; From 1eec30dac2ee5089f72e5430d4841cd93cd31841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 00:44:00 +0100 Subject: [PATCH 126/291] Avoid causing a gl error on startup on core contexts. --- ext/native/thin3d/GLQueueRunner.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 466a6d958a..87e7ef1d53 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -41,7 +41,9 @@ void GLQueueRunner::CreateDeviceObjects() { populate(GL_RENDERER); populate(GL_VERSION); populate(GL_SHADING_LANGUAGE_VERSION); - populate(GL_EXTENSIONS); // TODO: Not OK to query this in core profile! + if (!gl_extensions.IsCoreContext) { // Not OK to query this in core profile! + populate(GL_EXTENSIONS); + } } void GLQueueRunner::DestroyDeviceObjects() { From 8c5a94ce01578e248206289551cdff7aa48c7dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 00:50:29 +0100 Subject: [PATCH 127/291] gl-render-manager: Oops, fix scissor tests after clears --- ext/native/thin3d/GLQueueRunner.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 87e7ef1d53..3f5389cd6b 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -616,6 +616,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glClear(c.clear.clearMask); if (c.clear.scissorW > 0) { glDisable(GL_SCISSOR_TEST); + } else { + glEnable(GL_SCISSOR_TEST); } break; case GLRRenderCommand::INVALIDATE: From 4d6c0cfb32a7ef836fee6171fa13bd058d42bc52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 01:11:51 +0100 Subject: [PATCH 128/291] Buildfix --- SDL/SDLGLGraphicsContext.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDL/SDLGLGraphicsContext.h b/SDL/SDLGLGraphicsContext.h index 71f130a4f7..52ea68f018 100644 --- a/SDL/SDLGLGraphicsContext.h +++ b/SDL/SDLGLGraphicsContext.h @@ -19,7 +19,7 @@ public: void ShutdownFromRenderThread() override; void SwapBuffers() override { - renderManager_->Swap(); + // Do nothing, the render thread takes care of this. } Draw::DrawContext *GetDrawContext() override { From 20eb5666656451d179b960f6e1885ed6c7f4c88f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 11:19:48 +0100 Subject: [PATCH 129/291] Minor Qt cleanup, force OpenGL since we don't yet support Vulkan in Qt --- Qt/QtMain.cpp | 25 ++++++++++++++----------- Qt/QtMain.h | 16 ++++++++++------ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 74d8be6b2d..c9a9ac53a5 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -364,24 +364,28 @@ bool MainUI::event(QEvent *e) return true; } -void MainUI::initializeGL() -{ +void MainUI::initializeGL() { + if (g_Config.iGPUBackend != (int)GPUBackend::OPENGL) { + ILOG("Only GL supported under Qt - switching."); + g_Config.iGPUBackend = (int)GPUBackend::OPENGL; + } + #ifndef USING_GLES2 // Some core profile drivers elide certain extensions from GL_EXTENSIONS/etc. // glewExperimental allows us to force GLEW to search for the pointers anyway. - if (gl_extensions.IsCoreContext) + if (gl_extensions.IsCoreContext) { glewExperimental = true; + } glewInit(); // Unfortunately, glew will generate an invalid enum error, ignore. - if (gl_extensions.IsCoreContext) + if (gl_extensions.IsCoreContext) { glGetError(); + } #endif - ILOG("Initializing graphics context"); - - // OpenGL uses a background thread to do the main processing and only renders on the gl thread. - graphicsContext = new QtDummyGraphicsContext(); - if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { + // OpenGL uses a background thread to do the main processing and only renders on the gl thread. + ILOG("Initializing GL graphics context"); + graphicsContext = new QtGLGraphicsContext(); ILOG("Using thread, starting emu thread"); EmuThreadStart(); } else { @@ -390,8 +394,7 @@ void MainUI::initializeGL() graphicsContext->ThreadStart(); } -void MainUI::paintGL() -{ +void MainUI::paintGL() { #ifdef SDL SDL_PumpEvents(); #endif diff --git a/Qt/QtMain.h b/Qt/QtMain.h index cc39d5802b..404e50439e 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -44,9 +44,9 @@ QTM_USE_NAMESPACE // Input void SimulateGamepad(); -class QtDummyGraphicsContext : public DummyGraphicsContext { +class QtGLGraphicsContext : public GraphicsContext { public: - QtDummyGraphicsContext() { + QtGLGraphicsContext() { CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); SetGPUBackend(GPUBackend::OPENGL); @@ -55,12 +55,17 @@ public: assert(success); } - ~QtDummyGraphicsContext() { + ~QtGLGraphicsContext() { delete draw_; draw_ = nullptr; renderManager_ = nullptr; } + void Shutdown() override {} + void SwapInterval(int interval) override {} + void SwapBuffers() override {} + void Resize() override {} + Draw::DrawContext *GetDrawContext() override { return draw_; } @@ -123,7 +128,7 @@ protected: void EmuThreadJoin(); private: - QtDummyGraphicsContext *graphicsContext; + QtGLGraphicsContext *graphicsContext; float xscale, yscale; #if defined(MOBILE_DEVICE) @@ -139,8 +144,7 @@ extern MainUI* emugl; #ifndef SDL // Audio -class MainAudio: public QObject -{ +class MainAudio : public QObject { Q_OBJECT public: MainAudio() {} From b9b41f52c598a1964f13e25f4213c3f25859ec4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 12:02:44 +0100 Subject: [PATCH 130/291] Add a simple spinner to the game load screen to not look frozen. --- GPU/Directx9/FramebufferDX9.cpp | 6 ++---- GPU/GLES/FramebufferManagerGLES.cpp | 2 -- UI/EmuScreen.cpp | 11 ++++++++++- UI/EmuScreen.h | 1 + ext/native/ui/view.cpp | 25 ++++++++++++++++++++++++- ext/native/ui/view.h | 16 ++++++++++++++++ 6 files changed, 53 insertions(+), 8 deletions(-) diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index fa0235a2c5..6b6296097e 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -537,9 +537,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { } } - // TODO: SSE/NEON - // Could also make C fake-simd for 64-bit, two 8888 pixels fit in a register :) - void ConvertFromRGBA8888(u8 *dst, u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format) { + void ConvertFromBGRA8888(u8 *dst, u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format) { // Must skip stride in the cases below. Some games pack data into the cracks, like MotoGP. const u32 *src32 = (const u32 *)src; @@ -617,7 +615,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { // TODO: Handle the other formats? We don't currently create them, I think. const int dstByteOffset = (y * vfb->fb_stride + x) * dstBpp; // Pixel size always 4 here because we always request BGRA8888. - ConvertFromRGBA8888(Memory::GetPointer(fb_address + dstByteOffset), (u8 *)locked.pBits, vfb->fb_stride, locked.Pitch / 4, w, h, vfb->format); + ConvertFromBGRA8888(Memory::GetPointer(fb_address + dstByteOffset), (u8 *)locked.pBits, vfb->fb_stride, locked.Pitch / 4, w, h, vfb->format); offscreen->UnlockRect(); } else { ERROR_LOG_REPORT(G3D, "Unable to lock rect from %08x: %d,%d %dx%d of %dx%d", fb_address, rect.left, rect.top, rect.right, rect.bottom, vfb->renderWidth, vfb->renderHeight); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index fc0e04ff12..9cde5bf55d 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -643,8 +643,6 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_RASTER_STATE); } -// TODO: SSE/NEON -// Could also make C fake-simd for 64-bit, two 8888 pixels fit in a register :) void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format) { // Must skip stride in the cases below. Some games pack data into the cracks, like MotoGP. const u32 *src32 = (const u32 *)src; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index ce2886cd54..ab663a202b 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -862,13 +862,22 @@ void EmuScreen::CreateViews() { GameInfoBGView *loadingBG = root_->Add(new GameInfoBGView(gamePath_, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT))); TextView *loadingTextView = root_->Add(new TextView(sc->T("Loading game..."), new AnchorLayoutParams(bounds.centerX(), bounds.centerY(), NONE, NONE, true))); + static const int symbols[4] = { + I_CROSS, + I_CIRCLE, + I_SQUARE, + I_TRIANGLE + }; + Spinner *loadingSpinner = root_->Add(new Spinner(symbols, ARRAY_SIZE(symbols), new AnchorLayoutParams(bounds.centerX(), bounds.centerY() + 64, NONE, NONE, true))); + loadingSpinner_ = loadingSpinner; loadingTextView->SetShadow(true); loadingView_ = loadingTextView; loadingViewColor_ = loadingTextView->AddTween(new CallbackColorTween(0x00FFFFFF, 0x00FFFFFF, 0.2f, &bezierEaseInOut)); - loadingViewColor_->SetCallback([loadingBG, loadingTextView](View *v, uint32_t c) { + loadingViewColor_->SetCallback([loadingBG, loadingTextView, loadingSpinner](View *v, uint32_t c) { loadingBG->SetColor(c & 0xFFC0C0C0); loadingTextView->SetTextColor(c); + loadingSpinner->SetColor(alphaMul(c, 0.7f)); }); loadingViewColor_->Persist(); diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 1745e8728c..755bc487ce 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -101,4 +101,5 @@ private: UI::View *loadingView_ = nullptr; UI::CallbackColorTween *loadingViewColor_ = nullptr; UI::VisibilityTween *loadingViewVisible_ = nullptr; + UI::Spinner *loadingSpinner_ = nullptr; }; diff --git a/ext/native/ui/view.cpp b/ext/native/ui/view.cpp index 0585b62d27..58427c8715 100644 --- a/ext/native/ui/view.cpp +++ b/ext/native/ui/view.cpp @@ -816,6 +816,10 @@ void TextView::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz } void TextView::Draw(UIContext &dc) { + uint32_t textColor = hasTextColor_ ? textColor_ : dc.theme->infoStyle.fgColor; + if (!(textColor & 0xFF000000)) + return; + bool clip = false; if (measuredWidth_ > bounds_.w || measuredHeight_ > bounds_.h) clip = true; @@ -839,7 +843,6 @@ void TextView::Draw(UIContext &dc) { uint32_t shadowColor = 0x80000000; dc.DrawTextRect(text_.c_str(), bounds_.Offset(1.0f, 1.0f), shadowColor, textAlign_); } - uint32_t textColor = hasTextColor_ ? textColor_ : dc.theme->infoStyle.fgColor; dc.DrawTextRect(text_.c_str(), bounds_, textColor, textAlign_); if (clip) { dc.PopScissor(); @@ -1071,6 +1074,26 @@ void ProgressBar::Draw(UIContext &dc) { dc.DrawTextRect(temp, bounds_, 0xFFFFFFFF, ALIGN_CENTER); } +void Spinner::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + w = 48; + h = 48; +} + +void Spinner::Draw(UIContext &dc) { + if (!(color_ & 0xFF000000)) + return; + double t = time_now_d() * 1.3f; + double angle = fmod(t, M_PI * 2.0); + float r = bounds_.w * 0.5f; + double da = M_PI * 2.0 / numImages_; + for (int i = 0; i < numImages_; i++) { + double a = angle + i * da; + float x = (float)cos(a) * r; + float y = (float)sin(a) * r; + dc.Draw()->DrawImage(images_[i], bounds_.centerX() + x, bounds_.centerY() + y, 1.0f, color_, ALIGN_CENTER); + } +} + void TriggerButton::Touch(const TouchInput &input) { if (input.flags & TOUCH_DOWN) { if (bounds_.Contains(input.x, input.y)) { diff --git a/ext/native/ui/view.h b/ext/native/ui/view.h index af7fc2a1ce..06da7b98c6 100644 --- a/ext/native/ui/view.h +++ b/ext/native/ui/view.h @@ -882,6 +882,22 @@ private: float progress_; }; +class Spinner : public InertView { +public: + Spinner(const int *images, int numImages, LayoutParams *layoutParams = 0) + : InertView(layoutParams), images_(images), numImages_(numImages) { + } + + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; + void Draw(UIContext &dc) override; + void SetColor(uint32_t color) { color_ = color; } + +private: + const int *images_; + int numImages_; + uint32_t color_ = 0xFFFFFFFF; +}; + void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measured); void EventTriggered(Event *e, EventParams params); From b9081dd624b6434677a9327e23516b06c08c9c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 16:20:56 +0100 Subject: [PATCH 131/291] GL: Set a plain render state in DrawActiveTexture, without relying on the caller having called DisableState --- GPU/GLES/FramebufferManagerGLES.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 9cde5bf55d..dc56db2a40 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -423,6 +423,12 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float pos[i * 3 + 1] = pos[i * 3 + 1] * invDestH - 1.0f; } + // We always want a plain state here. + render_->SetNoBlendAndMask(0xF); + render_->SetDepth(false, false, GL_ALWAYS); + render_->SetStencilDisabled(); + render_->SetRaster(false, GL_CCW, GL_FALSE, GL_FALSE); + // Upscaling postshaders don't look well with linear if (flags & DRAWTEX_LINEAR) { render_->SetTextureSampler(0, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); From 86cfc411a48ca909c3da8937764db17e65a36922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 16:21:41 +0100 Subject: [PATCH 132/291] Remove the confusing "DisableState" across the codebase --- GPU/Common/FramebufferCommon.cpp | 5 ----- GPU/Common/FramebufferCommon.h | 1 - GPU/D3D11/FramebufferManagerD3D11.cpp | 9 --------- GPU/D3D11/FramebufferManagerD3D11.h | 2 -- GPU/Directx9/FramebufferDX9.cpp | 23 ++++++++--------------- GPU/Directx9/FramebufferDX9.h | 1 - GPU/Directx9/StencilBufferDX9.cpp | 1 - GPU/GLES/FramebufferManagerGLES.cpp | 6 ------ GPU/GLES/FramebufferManagerGLES.h | 1 - GPU/GLES/StencilBufferGLES.cpp | 3 +-- GPU/Vulkan/FramebufferVulkan.h | 1 - 11 files changed, 9 insertions(+), 44 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 1447ca62ff..03c0aad4c8 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -690,7 +690,6 @@ void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size, bool safe) { FlushBeforeCopy(); if (useBufferedRendering_ && vfb->fbo) { - DisableState(); GEBufferFormat fmt = vfb->format; if (vfb->last_frame_render + 1 < gpuStats.numFlips && isDisplayBuf) { // If we're not rendering to it, format may be wrong. Use displayFormat_ instead. @@ -731,7 +730,6 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int SetViewport2D(x, y, w, h); draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_); } - DisableState(); MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height, u1, v1); @@ -775,8 +773,6 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, GEBu float v0 = 0.0f, v1 = 1.0f; MakePixelTexture(srcPixels, srcPixelFormat, srcStride, 512, 272, u1, v1); - DisableState(); - struct CardboardSettings cardboardSettings; GetCardboardSettings(&cardboardSettings); @@ -951,7 +947,6 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { if (vfb->fbo) { DEBUG_LOG(FRAMEBUF, "Displaying FBO %08x", vfb->fb_address); - DisableState(); int uvRotation = useBufferedRendering_ ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 9ab59a4b0b..d88dced994 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -312,7 +312,6 @@ protected: bool UpdateSize(); void SetNumExtraFBOs(int num); - virtual void DisableState() = 0; void FlushBeforeCopy(); virtual void DecimateFBOs(); // keeping it virtual to let D3D do a little extra diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index c45ec45cd5..9cd78f97dc 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -197,13 +197,6 @@ void FramebufferManagerD3D11::SetDrawEngine(DrawEngineD3D11 *td) { drawEngine_ = td; } -void FramebufferManagerD3D11::DisableState() { - context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], nullptr, 0xFFFFFFFF); - context_->RSSetState(stockD3D11.rasterStateNoCull); - context_->OMSetDepthStencilState(stockD3D11.depthStencilDisabled, 0xFF); - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE); -} - void FramebufferManagerD3D11::CompilePostShader() { std::string vsSource; std::string psSource; @@ -731,8 +724,6 @@ void FramebufferManagerD3D11::DestroyAllFBOs() { tempFBOs_.clear(); SetNumExtraFBOs(0); - - DisableState(); } void FramebufferManagerD3D11::Resized() { diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index d951d60e7f..253bc8dd6e 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -65,8 +65,6 @@ public: } protected: - void DisableState() override; - // Used by ReadFramebufferToMemory and later framebuffer block copies void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) override; diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 6b6296097e..3d7e7c03b7 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -81,17 +81,6 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { D3DDECL_END() }; - void FramebufferManagerDX9::DisableState() { - dxstate.blend.disable(); - dxstate.cullMode.set(false, false); - dxstate.depthTest.disable(); - dxstate.scissorTest.disable(); - dxstate.stencilTest.disable(); - dxstate.colorMask.set(true, true, true, true); - dxstate.stencilMask.set(0xFF); - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); - } - FramebufferManagerDX9::FramebufferManagerDX9(Draw::DrawContext *draw) : FramebufferManagerCommon(draw), drawPixelsTex_(0), @@ -249,7 +238,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { } void FramebufferManagerDX9::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags) { - // TODO: StretchRect instead? + // TODO: StretchRect instead when possible? float coord[20] = { x,y,0, u0,v0, x+w,y,0, u1,v0, @@ -297,7 +286,13 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { } dxstate.texMipLodBias.set(0.0f); dxstate.texMaxMipLevel.set(0); - device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + dxstate.blend.disable(); + dxstate.cullMode.set(false, false); + dxstate.depthTest.disable(); + dxstate.scissorTest.disable(); + dxstate.stencilTest.disable(); + dxstate.colorMask.set(true, true, true, true); + dxstate.stencilMask.set(0xFF); HRESULT hr = device_->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coord, 5 * sizeof(float)); if (FAILED(hr)) { ERROR_LOG_REPORT(G3D, "DrawActiveTexture() failed: %08x", hr); @@ -725,8 +720,6 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { offscreenSurfaces_.clear(); SetNumExtraFBOs(0); - - DisableState(); } void FramebufferManagerDX9::Resized() { diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index dd1b3bd2ca..bc2ce7c31d 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -73,7 +73,6 @@ protected: void Bind2DShader() override; void BindPostShader(const PostShaderUniforms &uniforms) override; void SetViewport2D(int x, int y, int w, int h) override; - void DisableState() override; void DecimateFBOs() override; // Used by ReadFramebufferToMemory and later framebuffer block copies diff --git a/GPU/Directx9/StencilBufferDX9.cpp b/GPU/Directx9/StencilBufferDX9.cpp index 95f7b42718..6f51582cf2 100644 --- a/GPU/Directx9/StencilBufferDX9.cpp +++ b/GPU/Directx9/StencilBufferDX9.cpp @@ -181,7 +181,6 @@ bool FramebufferManagerDX9::NotifyStencilUpload(u32 addr, int size, bool skipZer shaderManagerDX9_->DirtyLastShader(); - DisableState(); dxstate.colorMask.set(false, false, false, true); dxstate.stencilTest.enable(); dxstate.stencilOp.set(D3DSTENCILOP_REPLACE, D3DSTENCILOP_REPLACE, D3DSTENCILOP_REPLACE); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index dc56db2a40..00f7da4195 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -80,10 +80,6 @@ const int MAX_PBO = 2; void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format); -void FramebufferManagerGLES::DisableState() { - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); -} - void FramebufferManagerGLES::CompileDraw2DProgram() { if (!draw2dprogram_) { std::string errorString; @@ -784,8 +780,6 @@ void FramebufferManagerGLES::DestroyAllFBOs() { tempFBOs_.clear(); SetNumExtraFBOs(0); - - DisableState(); } void FramebufferManagerGLES::Resized() { diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index c3f0594637..fb00c41858 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -69,7 +69,6 @@ public: protected: void SetViewport2D(int x, int y, int w, int h) override; - void DisableState() override; // Used by ReadFramebufferToMemory and later framebuffer block copies void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) override; diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 093694dddd..d29e2bbf56 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -142,8 +142,6 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe shaderManagerGL_->DirtyLastShader(); - DisableState(); - bool useBlit = gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT); // Our fragment shader (and discard) is slow. Since the source is 1x, we can stencil to 1x. @@ -169,6 +167,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe textureCacheGL_->ForgetLastTexture(); // We must bind the program after starting the render pass, and set the color mask after clearing. + render_->SetDepth(false, false, GL_ALWAYS); render_->Clear(0, 0, 0, GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 0x8, 0, 0, 0, 0); render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF); render_->BindProgram(stencilUploadProgram_); diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index 10d739642c..197802e4bc 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -89,7 +89,6 @@ protected: void Bind2DShader() override; void BindPostShader(const PostShaderUniforms &uniforms) override; void SetViewport2D(int x, int y, int w, int h) override; - void DisableState() override {} // Used by ReadFramebufferToMemory and later framebuffer block copies void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) override; From 0fe4e70aefa60e305777d12e1d09ab4751fef901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 16:47:04 +0100 Subject: [PATCH 133/291] Fix another way the scissor test could accidentally get disabled --- ext/native/thin3d/GLQueueRunner.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 3f5389cd6b..c8faa9958b 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -588,11 +588,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { #endif break; case GLRRenderCommand::CLEAR: - if (c.clear.scissorW > 0) { - glEnable(GL_SCISSOR_TEST); - glScissor(c.clear.scissorX, c.clear.scissorY, c.clear.scissorW, c.clear.scissorH); - } else { + // Scissor test is on, and should be on after leaving this case. If we disable it, + // we re-enable it at the end. + if (c.clear.scissorW == 0) { glDisable(GL_SCISSOR_TEST); + } else { + glScissor(c.clear.scissorX, c.clear.scissorY, c.clear.scissorW, c.clear.scissorH); } if (c.clear.colorMask != colorMask) { glColorMask(c.clear.colorMask & 1, (c.clear.colorMask >> 1) & 1, (c.clear.colorMask >> 2) & 1, (c.clear.colorMask >> 3) & 1); @@ -614,9 +615,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glClearStencil(c.clear.clearStencil); } glClear(c.clear.clearMask); - if (c.clear.scissorW > 0) { - glDisable(GL_SCISSOR_TEST); - } else { + if (c.clear.scissorW == 0) { glEnable(GL_SCISSOR_TEST); } break; From 625595c6cce2a103fad8eb301a864fec25c959ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 16:59:03 +0100 Subject: [PATCH 134/291] For some reason we use DrawActiveTexture in the GL stencil stuff, don't want to disable stencil unconditionally.. --- GPU/Common/FramebufferCommon.h | 1 + GPU/GLES/FramebufferManagerGLES.cpp | 8 +++++--- GPU/GLES/StencilBufferGLES.cpp | 5 +++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index d88dced994..89db174c8e 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -150,6 +150,7 @@ enum DrawTextureFlags { DRAWTEX_NEAREST = 0, DRAWTEX_LINEAR = 1, DRAWTEX_KEEP_TEX = 2, + DRAWTEX_KEEP_STENCIL = 4, }; inline Draw::DataFormat GEFormatToThin3D(int geFormat) { diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 00f7da4195..e951ec2467 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -419,11 +419,13 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float pos[i * 3 + 1] = pos[i * 3 + 1] * invDestH - 1.0f; } - // We always want a plain state here. + // We always want a plain state here, well, except for when it's used by the stencil stuff... render_->SetNoBlendAndMask(0xF); render_->SetDepth(false, false, GL_ALWAYS); - render_->SetStencilDisabled(); - render_->SetRaster(false, GL_CCW, GL_FALSE, GL_FALSE); + render_->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE); + if (!(flags & DRAWTEX_KEEP_STENCIL)) { + render_->SetStencilDisabled(); + } // Upscaling postshaders don't look well with linear if (flags & DRAWTEX_LINEAR) { diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index d29e2bbf56..170fb997f4 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -170,6 +170,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe render_->SetDepth(false, false, GL_ALWAYS); render_->Clear(0, 0, 0, GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 0x8, 0, 0, 0, 0); render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF); + render_->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE); render_->BindProgram(stencilUploadProgram_); render_->SetNoBlendAndMask(0x8); @@ -188,14 +189,14 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe render_->SetStencilOp(i, GL_REPLACE, GL_REPLACE, GL_REPLACE); render_->SetUniformF1(&u_stencilValue, i * (1.0f / 255.0f)); } - DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST); + DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST | DRAWTEX_KEEP_STENCIL); } if (useBlit) { draw_->BlitFramebuffer(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, Draw::FB_STENCIL_BIT, Draw::FB_BLIT_NEAREST); } - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); RebindFramebuffer(); return true; } From 8ad5b499a96f8779c40c4880f14c2fb23d4a2ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 10 Feb 2018 08:58:33 +0100 Subject: [PATCH 135/291] Improve assert messages in VulkanRenderManager (minor) --- ext/native/thin3d/VulkanRenderManager.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index ef262e9dc1..9ae9f4ae6d 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -754,13 +754,13 @@ void VulkanRenderManager::BeginSubmitFrame(int frame) { } else if (res == VK_ERROR_OUT_OF_DATE_KHR) { frameData.skipSwap = true; } else { - _assert_msg_(G3D, res == VK_SUCCESS, "vkAcquireNextImageKHR failed! result=%d", (int)res); + _assert_msg_(G3D, res == VK_SUCCESS, "vkAcquireNextImageKHR failed! result=%s", VulkanResultToString(res)); } VkCommandBufferBeginInfo begin{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; begin.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; res = vkBeginCommandBuffer(frameData.mainCmd, &begin); - _assert_msg_(G3D, res == VK_SUCCESS, "vkBeginCommandBuffer failed! result=%d", (int)res); + _assert_msg_(G3D, res == VK_SUCCESS, "vkBeginCommandBuffer failed! result=%s", VulkanResultToString(res)); queueRunner_.SetBackbuffer(framebuffers_[frameData.curSwapchainImage], swapchainImages_[frameData.curSwapchainImage].image); @@ -772,11 +772,11 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) { FrameData &frameData = frameData_[frame]; if (frameData.hasInitCommands) { VkResult res = vkEndCommandBuffer(frameData.initCmd); - _assert_msg_(G3D, res == VK_SUCCESS, "vkEndCommandBuffer failed (init)! result=%d", (int)res); + _assert_msg_(G3D, res == VK_SUCCESS, "vkEndCommandBuffer failed (init)! result=%s", VulkanResultToString(res)); } VkResult res = vkEndCommandBuffer(frameData.mainCmd); - _assert_msg_(G3D, res == VK_SUCCESS, "vkEndCommandBuffer failed (main)! result=%d", (int)res); + _assert_msg_(G3D, res == VK_SUCCESS, "vkEndCommandBuffer failed (main)! result=%s", VulkanResultToString(res)); VkCommandBuffer cmdBufs[2]; int numCmdBufs = 0; @@ -792,7 +792,7 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) { if (res == VK_ERROR_DEVICE_LOST) { _assert_msg_(G3D, false, "Lost the Vulkan device!"); } else { - _assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed (init)! result=%d", (int)res); + _assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed (init)! result=%s", VulkanResultToString(res)); } numCmdBufs = 0; } @@ -816,7 +816,7 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) { if (res == VK_ERROR_DEVICE_LOST) { _assert_msg_(G3D, false, "Lost the Vulkan device!"); } else { - _assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed (main, split=%d)! result=%d", (int)splitSubmit_, (int)res); + _assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed (main, split=%d)! result=%s", (int)splitSubmit_, VulkanResultToString(res)); } // When !triggerFence, we notify after syncing with Vulkan. @@ -848,7 +848,7 @@ void VulkanRenderManager::EndSubmitFrame(int frame) { if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) { // ignore, it'll be fine. this happens sometimes during resizes, and we do make sure to recreate the swap chain. } else { - _assert_msg_(G3D, res == VK_SUCCESS, "vkQueuePresentKHR failed! result=%d", (int)res); + _assert_msg_(G3D, res == VK_SUCCESS, "vkQueuePresentKHR failed! result=%s", VulkanResultToString(res)); } } else { frameData.skipSwap = false; From 081e15d1c878ab099895611a390f19fdad6c2e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 10 Feb 2018 09:06:43 +0100 Subject: [PATCH 136/291] Windows: Consistently shutdown the main thread after exiting the message loop. --- Windows/MainWindow.cpp | 1 - Windows/main.cpp | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 331b6a8c1d..f8b8cdd694 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -866,7 +866,6 @@ namespace MainWindow case WM_CLOSE: InputDevice::StopPolling(); - MainThread_Stop(); WindowsRawInput::Shutdown(); return DefWindowProc(hWnd,message,wParam,lParam); diff --git a/Windows/main.cpp b/Windows/main.cpp index 03dbf883cb..0e9259b93d 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -571,10 +571,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin break; } - if (!TranslateAccelerator(wnd, accel, &msg)) - { - if (!DialogManager::IsDialogMessage(&msg)) - { + if (!TranslateAccelerator(wnd, accel, &msg)) { + if (!DialogManager::IsDialogMessage(&msg)) { //and finally translate and dispatch TranslateMessage(&msg); DispatchMessage(&msg); @@ -582,6 +580,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin } } + MainThread_Stop(); + VFSShutdown(); InputDevice::StopPolling(); From d9af90e0169c01e6b03851ac9309215cba9394c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 10 Feb 2018 09:09:13 +0100 Subject: [PATCH 137/291] SDL: Fix issue with vulkan-to-opengl fallback --- SDL/SDLMain.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index e7d7faa15d..bbf4b42e2e 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -615,8 +615,6 @@ int main(int argc, char *argv[]) { GraphicsContext *graphicsContext = nullptr; SDL_Window *window = nullptr; - bool useEmuThread; - std::string error_message; if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { SDLGLGraphicsContext *ctx = new SDLGLGraphicsContext(); @@ -624,7 +622,6 @@ int main(int argc, char *argv[]) { printf("GL init error '%s'\n", error_message.c_str()); } graphicsContext = ctx; - useEmuThread = true; } else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext(); if (!ctx->Init(window, x, y, mode, &error_message)) { @@ -638,9 +635,10 @@ int main(int argc, char *argv[]) { } else { graphicsContext = ctx; } - useEmuThread = false; } + bool useEmuThread = g_Config.iGPUBackend == (int)GPUBackend::OPENGL; + SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); // Since we render from the main thread, there's nothing done here, but we call it to avoid confusion. From 3c93eaf16441639aeaee4a715dd30d18a407e78c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 10 Feb 2018 17:18:18 +0100 Subject: [PATCH 138/291] GL: Fix clearing alpha on stencil uploads. --- GPU/Common/FramebufferCommon.h | 2 +- GPU/GLES/FramebufferManagerGLES.cpp | 4 ++-- GPU/GLES/StencilBufferGLES.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 89db174c8e..b6febf7fa3 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -150,7 +150,7 @@ enum DrawTextureFlags { DRAWTEX_NEAREST = 0, DRAWTEX_LINEAR = 1, DRAWTEX_KEEP_TEX = 2, - DRAWTEX_KEEP_STENCIL = 4, + DRAWTEX_KEEP_STENCIL_ALPHA = 4, }; inline Draw::DataFormat GEFormatToThin3D(int geFormat) { diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index e951ec2467..dd0a0c2473 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -420,10 +420,10 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float } // We always want a plain state here, well, except for when it's used by the stencil stuff... - render_->SetNoBlendAndMask(0xF); render_->SetDepth(false, false, GL_ALWAYS); render_->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE); - if (!(flags & DRAWTEX_KEEP_STENCIL)) { + if (!(flags & DRAWTEX_KEEP_STENCIL_ALPHA)) { + render_->SetNoBlendAndMask(0xF); render_->SetStencilDisabled(); } diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 170fb997f4..4b59b60b96 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -189,7 +189,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe render_->SetStencilOp(i, GL_REPLACE, GL_REPLACE, GL_REPLACE); render_->SetUniformF1(&u_stencilValue, i * (1.0f / 255.0f)); } - DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST | DRAWTEX_KEEP_STENCIL); + DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST | DRAWTEX_KEEP_STENCIL_ALPHA); } if (useBlit) { From 2bec3bf3acca6ba235cd774e3244c2bc009e3a89 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Feb 2018 16:12:33 -0800 Subject: [PATCH 139/291] Windows: Trigger StopThread() on shutdown. Otherwise, we end up hanging in the loop waiting for emuThreadState to become STOPPED. It actually has, but ThreadFrame() will block until a new frame is queued... while will never happen, because the emuthread has stopped. --- Common/GraphicsContext.h | 1 + Windows/EmuThread.cpp | 3 +++ Windows/GPU/WindowsGLContext.cpp | 5 +++++ Windows/GPU/WindowsGLContext.h | 1 + 4 files changed, 10 insertions(+) diff --git a/Common/GraphicsContext.h b/Common/GraphicsContext.h index 66afcd94da..5dfec7f6d9 100644 --- a/Common/GraphicsContext.h +++ b/Common/GraphicsContext.h @@ -32,6 +32,7 @@ public: virtual void ThreadStart() {} virtual bool ThreadFrame() { return true; } virtual void ThreadEnd() {} + virtual void StopThread() {} virtual Draw::DrawContext *GetDrawContext() = 0; }; diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 5b9d1faca5..4e18eb1f53 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -86,6 +86,9 @@ static void EmuThreadFunc(GraphicsContext *graphicsContext) { emuThreadState = (int)EmuThreadState::STOPPED; NativeShutdownGraphics(); + + // Ask the main thread to stop. This prevents a hang on a race condition. + graphicsContext->StopThread(); } static void EmuThreadStart(GraphicsContext *graphicsContext) { diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 7962d3a817..b5dfc831d0 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -432,3 +432,8 @@ bool WindowsGLContext::ThreadFrame() { void WindowsGLContext::ThreadEnd() { renderManager_->ThreadEnd(); } + +void WindowsGLContext::StopThread() { + renderManager_->WaitUntilQueueIdle(); + renderManager_->StopThread(); +} diff --git a/Windows/GPU/WindowsGLContext.h b/Windows/GPU/WindowsGLContext.h index 38c9494947..1303aece79 100644 --- a/Windows/GPU/WindowsGLContext.h +++ b/Windows/GPU/WindowsGLContext.h @@ -29,6 +29,7 @@ public: void ThreadStart() override; void ThreadEnd() override; bool ThreadFrame() override; + void StopThread() override; Draw::DrawContext *GetDrawContext() override { return draw_; } From 48b4a5f3782d04aa04350298770696f5fd813a7a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Feb 2018 16:19:24 -0800 Subject: [PATCH 140/291] Android: Fix race condition on shutdown. --- android/jni/AndroidJavaGLContext.cpp | 1 - android/jni/AndroidJavaGLContext.h | 5 +++++ android/jni/app-android.cpp | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/android/jni/AndroidJavaGLContext.cpp b/android/jni/AndroidJavaGLContext.cpp index 4671cb7943..0f0937db08 100644 --- a/android/jni/AndroidJavaGLContext.cpp +++ b/android/jni/AndroidJavaGLContext.cpp @@ -27,5 +27,4 @@ void AndroidJavaEGLGraphicsContext::ShutdownFromRenderThread() { } void AndroidJavaEGLGraphicsContext::Shutdown() { - // TODO } diff --git a/android/jni/AndroidJavaGLContext.h b/android/jni/AndroidJavaGLContext.h index 10b63c61bc..44f062bd78 100644 --- a/android/jni/AndroidJavaGLContext.h +++ b/android/jni/AndroidJavaGLContext.h @@ -44,6 +44,11 @@ public: renderManager_->ThreadEnd(); } + void StopThread() override { + renderManager_->WaitUntilQueueIdle(); + renderManager_->StopThread(); + } + private: Draw::DrawContext *draw_ = nullptr; GLRenderManager *renderManager_ = nullptr; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index d62e0f29e4..2bf386e315 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -196,6 +196,9 @@ static void EmuThreadFunc() { NativeShutdownGraphics(); + // Also ask the main thread to stop, so it doesn't hang waiting for a new frame. + graphicsContext->StopThread(); + gJvm->DetachCurrentThread(); ILOG("Leaving emu thread"); } From a85a88e112f8d920bf442db1454892cb194743fe Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Feb 2018 16:23:05 -0800 Subject: [PATCH 141/291] SDL: Apply shutdown race condition fix. --- Qt/QtMain.cpp | 1 + Qt/QtMain.h | 5 +++++ SDL/SDLGLGraphicsContext.h | 5 +++++ SDL/SDLMain.cpp | 1 + 4 files changed, 12 insertions(+) diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index c9a9ac53a5..a2596d1368 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -208,6 +208,7 @@ void MainUI::EmuThreadFunc() { emuThreadState = (int)EmuThreadState::STOPPED; NativeShutdownGraphics(); + graphicsContext->StopThread(); } void MainUI::EmuThreadStart() { diff --git a/Qt/QtMain.h b/Qt/QtMain.h index 404e50439e..191dd320ec 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -82,6 +82,11 @@ public: renderManager_->ThreadEnd(); } + void StopThread() override { + renderManager_->WaitUntilQueueIdle(); + renderManager_->StopThread(); + } + private: Draw::DrawContext *draw_ = nullptr; GLRenderManager *renderManager_ = nullptr; diff --git a/SDL/SDLGLGraphicsContext.h b/SDL/SDLGLGraphicsContext.h index 52ea68f018..2695ebf64d 100644 --- a/SDL/SDLGLGraphicsContext.h +++ b/SDL/SDLGLGraphicsContext.h @@ -38,6 +38,11 @@ public: renderManager_->ThreadEnd(); } + void StopThread() override { + renderManager_->WaitUntilQueueIdle(); + renderManager_->StopThread(); + } + private: Draw::DrawContext *draw_ = nullptr; SDL_Window *window_; diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index bbf4b42e2e..bdc6c6d973 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -423,6 +423,7 @@ static void EmuThreadFunc(GraphicsContext *graphicsContext) { emuThreadState = (int)EmuThreadState::STOPPED; NativeShutdownGraphics(); + graphicsContext->StopThread(); } static void EmuThreadStart(GraphicsContext *context) { From 586e35ad2383d1128e7cbdf024149f40d49a8e87 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Feb 2018 16:23:34 -0800 Subject: [PATCH 142/291] Windows: Prevent shutdown lag for non-GL. For Vulkan/D3D, it was taking an extra second to quit. --- Windows/EmuThread.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 4e18eb1f53..b211783f6a 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -234,6 +234,10 @@ void MainThreadFunc() { } } Core_Stop(); + if (!useEmuThread) { + // Process the shutdown. Without this, non-GL delays 800ms on shutdown. + Core_Run(g_graphicsContext); + } Core_WaitInactive(800); g_inLoop = false; From d496b4da9abc3a90c11096506dfa799904f9f057 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Feb 2018 16:24:36 -0800 Subject: [PATCH 143/291] Windows: Allow GL thread on graphics restart. Unfortunately, it no longer works to go Vulkan -> OpenGL, and used to... --- Windows/MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index f8b8cdd694..11edd34f7a 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -915,7 +915,7 @@ namespace MainWindow MainThread_Stop(); coreState = CORE_POWERUP; ResetUIState(); - MainThread_Start(false); + MainThread_Start(g_Config.iGPUBackend == (int)GPUBackend::OPENGL); InputDevice::BeginPolling(); break; From 9a40a5971bb84282780701abf80a22d3cc6da965 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Feb 2018 16:54:25 -0800 Subject: [PATCH 144/291] GLES: Prevent crash on screenshot without buffers. It still fails for some reason, but that's better than a segfault. --- ext/native/thin3d/thin3d_gl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 6d5513de29..0b6f216891 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -735,7 +735,7 @@ bool OpenGLContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBit aspect |= GL_DEPTH_BUFFER_BIT; if (channelBits & FB_STENCIL_BIT) aspect |= GL_STENCIL_BUFFER_BIT; - renderManager_.CopyFramebufferToMemorySync(fb->framebuffer, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride); + renderManager_.CopyFramebufferToMemorySync(fb ? fb->framebuffer : nullptr, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride); return true; } From 813c376aed4259f41116bfe5336dfa4fd823a202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 11 Feb 2018 12:47:08 +0100 Subject: [PATCH 145/291] Tiny change to work around internal compiler error (!) in 32-bit builds with latest MSVC update --- Core/MIPS/MIPSIntVFPU.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index 784cba75ca..174b211400 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -1360,8 +1360,8 @@ namespace MIPSInt { for (int i = 0; i < n; i++) { - d[i] = 0.0f; - for (int k = 0; k < n; k++) + d[i] = s[i*4] * t[0]; + for (int k = 1; k < n; k++) { d[i] += s[i*4+k] * t[k]; } @@ -1371,7 +1371,8 @@ namespace MIPSInt { Reporting::ReportMessage("Trying to interpret instruction that can't be interpreted (BADVTFM)"); _dbg_assert_msg_(CPU,0,"Trying to interpret instruction that can't be interpreted (BADVTFM)"); - memset(d, 0, sizeof(d)); + for (int i = 0; i < n; i++) + d[i] = 0.0; } WriteVector(d, sz, vd); PC += 4; From 0e2a586c1b358dece002192ec67b7fdfa8957a2b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 07:03:23 -0800 Subject: [PATCH 146/291] Global: Fix some type comparison/shadow warnings. --- Common/Vulkan/VulkanMemory.cpp | 4 ++-- Core/CwCheat.cpp | 2 +- Core/ELF/ElfReader.cpp | 2 +- Core/FileSystems/BlobFileSystem.cpp | 6 +++--- GPU/Vulkan/DebugVisVulkan.cpp | 2 +- ext/native/thin3d/GLQueueRunner.cpp | 18 +++++++++--------- ext/native/thin3d/GLRenderManager.h | 2 +- ext/native/thin3d/VulkanQueueRunner.cpp | 4 ++-- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Common/Vulkan/VulkanMemory.cpp b/Common/Vulkan/VulkanMemory.cpp index 54c2cb6f46..4460a57492 100644 --- a/Common/Vulkan/VulkanMemory.cpp +++ b/Common/Vulkan/VulkanMemory.cpp @@ -283,9 +283,9 @@ bool VulkanDeviceAllocator::AllocateFromSlab(Slab &slab, size_t &start, size_t b int VulkanDeviceAllocator::ComputeUsagePercent() const { int blockSum = 0; int blocksUsed = 0; - for (int i = 0; i < slabs_.size(); i++) { + for (size_t i = 0; i < slabs_.size(); i++) { blockSum += (int)slabs_[i].usage.size(); - for (int j = 0; j < slabs_[i].usage.size(); j++) { + for (size_t j = 0; j < slabs_[i].usage.size(); j++) { blocksUsed += slabs_[i].usage[j] != 0 ? 1 : 0; } } diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index 0b14aa764a..0c39d9fe2f 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -351,7 +351,7 @@ std::vector CWCheatEngine::GetCodesList() { // It also goes through other "_" lines, but they all have to meet this requirement anyway // so we don't have to specify any syntax checks here that are made by cheat engine. if (line.length() >= 5 && line[0] == '_') { - for (int i = 4; i < line.length(); i++) { + for (size_t i = 4; i < line.length(); i++) { if (line[i] != ' ') { validCheatLine = true; break; diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index b68e7775b8..68f7531e2d 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -29,7 +29,7 @@ const char *ElfReader::GetSectionName(int section) const { return nullptr; int nameOffset = sections[section].sh_name; - if (nameOffset < 0 || nameOffset >= size_) { + if (nameOffset < 0 || (size_t)nameOffset >= size_) { ERROR_LOG(LOADER, "ELF: Bad name offset %d in section %d (max = %d)", nameOffset, section, (int)size_); return nullptr; } diff --git a/Core/FileSystems/BlobFileSystem.cpp b/Core/FileSystems/BlobFileSystem.cpp index b72b69ff30..b0a7639b39 100644 --- a/Core/FileSystems/BlobFileSystem.cpp +++ b/Core/FileSystems/BlobFileSystem.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017- PPSSPP Project. +// Copyright (c) 2017- PPSSPP Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -50,9 +50,9 @@ void BlobFileSystem::CloseFile(u32 handle) { size_t BlobFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) { auto entry = entries_.find(handle); if (entry != entries_.end()) { - size_t readSize = fileLoader_->ReadAt(entry->second, size, pointer); + s64 readSize = fileLoader_->ReadAt(entry->second, size, pointer); entry->second += readSize; - return readSize; + return (size_t)readSize; } return 0; } diff --git a/GPU/Vulkan/DebugVisVulkan.cpp b/GPU/Vulkan/DebugVisVulkan.cpp index 7bfc54bdeb..9002f82a7d 100644 --- a/GPU/Vulkan/DebugVisVulkan.cpp +++ b/GPU/Vulkan/DebugVisVulkan.cpp @@ -58,7 +58,7 @@ void DrawAllocatorVis(UIContext *ui, GPUInterface *gpu) { uint32_t *wideData = (uint32_t *)initData.data(); // Convert to nice colors. If we really wanted to save on memory, we could use a 16-bit texture... - for (int j = 0; j < usage.size(); j++) { + for (size_t j = 0; j < usage.size(); j++) { switch (usage[j]) { case 0: wideData[j] = 0xFF333333; break; case 1: wideData[j] = 0xFF33FF33; break; diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index c8faa9958b..e37b411e69 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -65,7 +65,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { GLuint boundTexture = (GLuint)-1; bool allocatedTextures = false; - for (int i = 0; i < steps.size(); i++) { + for (size_t i = 0; i < steps.size(); i++) { const GLRInitStep &step = steps[i]; switch (step.stepType) { case GLRInitStepType::CREATE_TEXTURE: @@ -98,9 +98,9 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { GLRProgram *program = step.create_program.program; program->program = glCreateProgram(); _assert_msg_(G3D, step.create_program.num_shaders > 0, "Can't create a program with zero shaders"); - for (int i = 0; i < step.create_program.num_shaders; i++) { - _dbg_assert_msg_(G3D, step.create_program.shaders[i]->shader, "Can't create a program with a null shader"); - glAttachShader(program->program, step.create_program.shaders[i]->shader); + for (int j = 0; j < step.create_program.num_shaders; j++) { + _dbg_assert_msg_(G3D, step.create_program.shaders[j]->shader, "Can't create a program with a null shader"); + glAttachShader(program->program, step.create_program.shaders[j]->shader); } for (auto iter : program->semantics_) { @@ -161,15 +161,15 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { glUseProgram(program->program); // Query all the uniforms. - for (int i = 0; i < program->queries_.size(); i++) { - auto &x = program->queries_[i]; + for (size_t j = 0; j < program->queries_.size(); j++) { + auto &x = program->queries_[j]; assert(x.name); *x.dest = glGetUniformLocation(program->program, x.name); } // Run initializers. - for (int i = 0; i < program->initialize_.size(); i++) { - auto &init = program->initialize_[i]; + for (size_t j = 0; j < program->initialize_.size(); j++) { + auto &init = program->initialize_[j]; GLint uniform = *init.uniform; if (uniform != -1) { switch (init.type) { @@ -399,7 +399,7 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) { } void GLQueueRunner::RunSteps(const std::vector &steps) { - for (int i = 0; i < steps.size(); i++) { + for (size_t i = 0; i < steps.size(); i++) { const GLRStep &step = *steps[i]; switch (step.stepType) { case GLRStepType::RENDER: diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 8b489c197d..2e50f392a5 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -267,7 +267,7 @@ public: step.create_program.program->initialize_ = initalizers; step.create_program.support_dual_source = supportDualSource; _assert_msg_(G3D, shaders.size() > 0, "Can't create a program with zero shaders"); - for (int i = 0; i < shaders.size(); i++) { + for (size_t i = 0; i < shaders.size(); i++) { step.create_program.shaders[i] = shaders[i]; } #ifdef _DEBUG diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 5cd4008386..6c04fd3d30 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -241,7 +241,7 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vector &steps) { ILOG("======================================="); - for (int i = 0; i < steps.size(); i++) { + for (size_t i = 0; i < steps.size(); i++) { const VKRStep &step = *steps[i]; switch (step.stepType) { case VKRStepType::RENDER: From 0474ff5c238bd79110faedf85a304fc4128bc8a4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 08:12:51 -0800 Subject: [PATCH 147/291] GLES: Use aligned memory for textures. We use SSE on them, and they used to be aligned, and must be aligned in PSP RAM, so keep them aligned. This only really affects 32-bit, since allocs will typically be aligned on 64-bit anyway. Fixes #10601. --- GPU/GLES/DepalettizeShaderGLES.cpp | 2 +- GPU/GLES/DrawEngineGLES.cpp | 6 +++--- GPU/GLES/FramebufferManagerGLES.cpp | 2 +- GPU/GLES/TextureCacheGLES.cpp | 10 +++++----- ext/native/thin3d/GLQueueRunner.cpp | 7 ++++++- ext/native/thin3d/GLQueueRunner.h | 5 +++++ ext/native/thin3d/GLRenderManager.h | 3 ++- 7 files changed, 23 insertions(+), 12 deletions(-) diff --git a/GPU/GLES/DepalettizeShaderGLES.cpp b/GPU/GLES/DepalettizeShaderGLES.cpp index 49e1b36f3c..77614c93df 100644 --- a/GPU/GLES/DepalettizeShaderGLES.cpp +++ b/GPU/GLES/DepalettizeShaderGLES.cpp @@ -95,7 +95,7 @@ GLRTexture *DepalShaderCacheGLES::GetClutTexture(GEPaletteFormat clutFormat, con uint8_t *clutCopy = new uint8_t[1024]; memcpy(clutCopy, rawClut, 1024); - render_->TextureImage(tex->texture, 0, texturePixels, 1, components, components2, dstFmt, clutCopy, false); + render_->TextureImage(tex->texture, 0, texturePixels, 1, components, components2, dstFmt, clutCopy, GLRAllocType::NEW, false); tex->lastFrame = gpuStats.numFlips; texCache_[clutId] = tex; diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 5988ee5fa1..bb0676719c 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -777,7 +777,7 @@ void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float uint8_t *pos_data = new uint8_t[size * sizeof(float) * 4]; memcpy(pos_data, pos, size * sizeof(float) * 4); data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D); - renderManager_->TextureImage(data_tex[0], 0, size, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, pos_data, false); + renderManager_->TextureImage(data_tex[0], 0, size, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, pos_data, GLRAllocType::NEW, false); renderManager_->FinalizeTexture(data_tex[0], 0, false); renderManager_->BindTexture(4, data_tex[0]); @@ -788,7 +788,7 @@ void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float uint8_t *tex_data = new uint8_t[size * sizeof(float) * 4]; memcpy(tex_data, pos, size * sizeof(float) * 4); data_tex[1] = renderManager_->CreateTexture(GL_TEXTURE_2D); - renderManager_->TextureImage(data_tex[1], 0, size, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, tex_data, false); + renderManager_->TextureImage(data_tex[1], 0, size, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, tex_data, GLRAllocType::NEW, false); renderManager_->FinalizeTexture(data_tex[1], 0, false); renderManager_->BindTexture(5, data_tex[1]); } @@ -800,7 +800,7 @@ void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float uint8_t *col_data = new uint8_t[sizeColor * sizeof(float) * 4]; memcpy(col_data, col, sizeColor * sizeof(float) * 4); - renderManager_->TextureImage(data_tex[2], 0, sizeColor, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, col_data, false); + renderManager_->TextureImage(data_tex[2], 0, sizeColor, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, col_data, GLRAllocType::NEW, false); renderManager_->FinalizeTexture(data_tex[2], 0, false); renderManager_->BindTexture(6, data_tex[2]); } diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index dd0a0c2473..351579744f 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -367,7 +367,7 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma break; } } - render_->TextureImage(drawPixelsTex_, 0, texWidth, height, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, convBuf, false); + render_->TextureImage(drawPixelsTex_, 0, texWidth, height, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, convBuf, GLRAllocType::NEW, false); render_->FinalizeTexture(drawPixelsTex_, 0, false); // TODO: Return instead? diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index d16f14f372..1c1ff3551d 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -714,7 +714,7 @@ u8 *TextureCacheGLES::DecodeTextureLevelOld(GETextureFormat format, GEPaletteFor decPitch = bufw * pixelSize; } - uint8_t *texBuf = new uint8_t[std::max(w, bufw) * h * pixelSize]; + uint8_t *texBuf = (uint8_t *)AllocateAlignedMemory(std::max(w, bufw) * h * pixelSize, 16); DecodeTextureLevel(texBuf, decPitch, format, clutformat, texaddr, level, bufw, true, false, false); return texBuf; } @@ -755,7 +755,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r PROFILE_THIS_SCOPE("replacetex"); int bpp = replaced.Format(level) == ReplacedTextureFormat::F_8888 ? 4 : 2; - uint8_t *rearrange = new uint8_t[w * h * bpp]; + uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(w * h * bpp, 16); replaced.Load(level, rearrange, bpp * w); pixelData = rearrange; @@ -785,7 +785,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r } if (scaleFactor > 1) { - uint8_t *rearrange = new uint8_t[w * scaleFactor * h * scaleFactor * 4]; + uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(w * scaleFactor * h * scaleFactor * 4, 16); scaler.ScaleAlways((u32 *)rearrange, (u32 *)pixelData, dstFmt, w, h, scaleFactor); pixelData = rearrange; delete [] finalBuf; @@ -817,9 +817,9 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r } else { PROFILE_THIS_SCOPE("loadtex"); if (IsFakeMipmapChange()) - render_->TextureImage(entry.textureName, 0, w, h, components, components2, dstFmt, pixelData); + render_->TextureImage(entry.textureName, 0, w, h, components, components2, dstFmt, pixelData, GLRAllocType::ALIGNED); else - render_->TextureImage(entry.textureName, level, w, h, components, components2, dstFmt, pixelData); + render_->TextureImage(entry.textureName, level, w, h, components, components2, dstFmt, pixelData, GLRAllocType::ALIGNED); } } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index e37b411e69..1053752af1 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -1,3 +1,4 @@ +#include "Common/MemoryUtil.h" #include "Core/Reporting.h" #include "GLQueueRunner.h" #include "GLRenderManager.h" @@ -241,7 +242,11 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { // For things to show in RenderDoc, need to split into glTexImage2D(..., nullptr) and glTexSubImage. glTexImage2D(tex->target, step.texture_image.level, step.texture_image.internalFormat, step.texture_image.width, step.texture_image.height, 0, step.texture_image.format, step.texture_image.type, step.texture_image.data); allocatedTextures = true; - delete[] step.texture_image.data; + if (step.texture_image.allocType == GLRAllocType::ALIGNED) { + FreeAlignedMemory(step.texture_image.data); + } else { + delete[] step.texture_image.data; + } CHECK_GL_ERROR_IF_DEBUG(); tex->wrapS = GL_CLAMP_TO_EDGE; tex->wrapT = GL_CLAMP_TO_EDGE; diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 63a17503c4..9119b0d05f 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -19,6 +19,10 @@ struct GLOffset2D { int x, y; }; +enum class GLRAllocType { + NEW, + ALIGNED, +}; class GLRShader; class GLRTexture; @@ -242,6 +246,7 @@ struct GLRInitStep { int level; int width; int height; + GLRAllocType allocType; bool linearFilter; uint8_t *data; // owned, delete[]-d } texture_image; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 2e50f392a5..c3b473e605 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -337,7 +337,7 @@ public: } // Takes ownership over the data pointer and delete[]-s it. - void TextureImage(GLRTexture *texture, int level, int width, int height, GLenum internalFormat, GLenum format, GLenum type, uint8_t *data, bool linearFilter = false) { + void TextureImage(GLRTexture *texture, int level, int width, int height, GLenum internalFormat, GLenum format, GLenum type, uint8_t *data, GLRAllocType allocType = GLRAllocType::NEW, bool linearFilter = false) { GLRInitStep step{ GLRInitStepType::TEXTURE_IMAGE }; step.texture_image.texture = texture; step.texture_image.data = data; @@ -347,6 +347,7 @@ public: step.texture_image.level = level; step.texture_image.width = width; step.texture_image.height = height; + step.texture_image.allocType = allocType; step.texture_image.linearFilter = linearFilter; initSteps_.push_back(step); } From fcc2b59c575881cbe9d72d67709c9e262502ffab Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 11:30:38 -0800 Subject: [PATCH 148/291] GLES: Wait for queue idle properly. Need to wait for anything ready for run. Not everything will have been submitted. --- ext/native/thin3d/GLRenderManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index d5ee6be8b3..d15448e898 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -514,7 +514,7 @@ void GLRenderManager::WaitUntilQueueIdle() { std::unique_lock lock(frameData.push_mutex); // Ignore unsubmitted frames. - while (!frameData.readyForFence && !frameData.readyForSubmit) { + while (!frameData.readyForFence && frameData.readyForRun) { VLOG("PUSH: Waiting for frame[%d].readyForFence = 1 (wait idle)", i); frameData.push_condVar.wait(lock); } From cdf378d20c2fd5891f69043046e2908eaae447e0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 11:40:11 -0800 Subject: [PATCH 149/291] GLES: Prevent race condition on shutdown. emuThreadState might become STOPPED before the last frame has been run, which can cause WaitUntilQueueIdle to hang. It's simpler just to wait until StopThread() is called, since it now is. This will line up properly with run_. --- Qt/QtMain.cpp | 4 ++-- SDL/SDLMain.cpp | 4 ++-- Windows/EmuThread.cpp | 4 ++-- android/jni/app-android.cpp | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index a2596d1368..297a31c661 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -248,9 +248,9 @@ MainUI::~MainUI() if (emuThreadState != (int)EmuThreadState::DISABLED) { ILOG("EmuThreadStop"); EmuThreadStop(); - while (emuThreadState != (int)EmuThreadState::STOPPED) { + while (graphicsContext->ThreadFrame()) { // Need to keep eating frames to allow the EmuThread to exit correctly. - graphicsContext->ThreadFrame(); + continue; } EmuThreadJoin(); } diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index bdc6c6d973..9cd5af04a9 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -896,9 +896,9 @@ int main(int argc, char *argv[]) { if (useEmuThread) { EmuThreadStop(); - while (emuThreadState != (int)EmuThreadState::STOPPED) { + while (graphicsContext->ThreadFrame()) { // Need to keep eating frames to allow the EmuThread to exit correctly. - graphicsContext->ThreadFrame(); + continue; } EmuThreadJoin(); } diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index b211783f6a..27a34fcc7b 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -244,9 +244,9 @@ void MainThreadFunc() { if (useEmuThread) { EmuThreadStop(); - while (emuThreadState != (int)EmuThreadState::STOPPED) { + while (graphicsContext->ThreadFrame()) { // Need to keep eating frames to allow the EmuThread to exit correctly. - graphicsContext->ThreadFrame(); + continue; } EmuThreadJoin(); } diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 2bf386e315..747629bde6 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -511,8 +511,8 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_pause(JNIEnv *, jclass) { extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { if (useCPUThread && graphicsContext) { EmuThreadStop(); - while (emuThreadState != (int)EmuThreadState::STOPPED) { - graphicsContext->ThreadFrame(); + while (graphicsContext->ThreadFrame()) { + continue; } EmuThreadJoin(); } @@ -546,8 +546,8 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, graphicsContext->ThreadEnd(); if (useCPUThread) { EmuThreadStop(); - while (emuThreadState != (int)EmuThreadState::STOPPED) { - graphicsContext->ThreadFrame(); + while (graphicsContext->ThreadFrame()) { + continue; } EmuThreadJoin(); } else { From df5144b94cbf92313845011889f511f229ff1ed9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 11:46:26 -0800 Subject: [PATCH 150/291] iOS: Attempt to fix shutdown race condition. Not really tested, but should be necessary... --- ios/ViewController.mm | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/ios/ViewController.mm b/ios/ViewController.mm index a214286791..f55496917c 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -58,6 +58,11 @@ public: void ThreadEnd() override { renderManager_->ThreadEnd(); } + + void StopThread() override { + renderManager_->WaitUntilQueueIdle(); + renderManager_->StopThread(); + } private: Draw::DrawContext *draw_; GLRenderManager *renderManager_; @@ -170,7 +175,6 @@ static GraphicsContext *graphicsContext; graphicsContext = new IOSGraphicsContext(); - NativeInitGraphics(graphicsContext); graphicsContext->ThreadStart(); dp_xscale = (float)dp_xres / (float)pixel_xres; @@ -190,11 +194,18 @@ static GraphicsContext *graphicsContext; #endif dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + NativeInitGraphics(graphicsContext); + while (threadEnabled) { NativeUpdate(); NativeRender(graphicsContext); time_update(); } + + NativeShutdownGraphics(); + + // Also ask the main thread to stop, so it doesn't hang waiting for a new frame. + graphicsContext->StopThread(); }); } @@ -220,8 +231,10 @@ static GraphicsContext *graphicsContext; } #endif threadEnabled = false; + while (graphicsContext->ThreadFrame()) { + continue; + } graphicsContext->ThreadEnd(); - NativeShutdownGraphics(); graphicsContext->Shutdown(); delete graphicsContext; graphicsContext = NULL; From adbd8d005c24766fcbd9fcd16854ae57d2888644 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 11:10:02 -0800 Subject: [PATCH 151/291] Cheats: Fix a debug assertion. --- Core/CwCheat.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index 0c39d9fe2f..71e6070399 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -30,10 +30,11 @@ void hleCheat(u64 userdata, int cyclesLate); static inline std::string TrimString(const std::string &s) { auto wsfront = std::find_if_not(s.begin(), s.end(), [](int c) { - return std::isspace(c); + // isspace() expects 0 - 255, so convert any sign-extended value. + return std::isspace(c & 0xFF); }); auto wsback = std::find_if_not(s.rbegin(), s.rend(), [](int c){ - return std::isspace(c); + return std::isspace(c & 0xFF); }).base(); return wsback > wsfront ? std::string(wsfront, wsback) : std::string(); } From 9eb51a6a3609780b92a2779514afcbfec0df5e64 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 11:17:34 -0800 Subject: [PATCH 152/291] GLES: Use mapped device memory when possible. --- ext/native/thin3d/GLQueueRunner.cpp | 3 + ext/native/thin3d/GLRenderManager.cpp | 87 +++++++++++++++++++++------ ext/native/thin3d/GLRenderManager.h | 31 +++++++++- 3 files changed, 99 insertions(+), 22 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 1053752af1..360fa54dd0 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -770,6 +770,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { // TODO: Add fast path for glBindVertexBuffer GLRInputLayout *layout = c.bindVertexBuffer.inputLayout; GLuint buf = c.bindVertexBuffer.buffer ? c.bindVertexBuffer.buffer->buffer : 0; + assert(!c.bindVertexBuffer.buffer->Mapped()); if (buf != curArrayBuffer) { glBindBuffer(GL_ARRAY_BUFFER, buf); curArrayBuffer = buf; @@ -797,12 +798,14 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { Crash(); } else if (c.bind_buffer.target == GL_ELEMENT_ARRAY_BUFFER) { GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0; + assert(!c.bind_buffer.buffer->Mapped()); if (buf != curElemArrayBuffer) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); curElemArrayBuffer = buf; } } else { GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0; + assert(!c.bind_buffer.buffer->Mapped()); glBindBuffer(c.bind_buffer.target, buf); } break; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index d15448e898..d66deb5d4f 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -421,6 +421,11 @@ void GLRenderManager::Run(int frame) { BeginSubmitFrame(frame); FrameData &frameData = frameData_[frame]; + for (auto iter : frameData.activePushBuffers) { + iter->Flush(); + iter->UnmapDevice(); + } + auto &stepsOnThread = frameData_[frame].steps; auto &initStepsOnThread = frameData_[frame].initSteps; // queueRunner_.LogSteps(stepsOnThread); @@ -429,6 +434,10 @@ void GLRenderManager::Run(int frame) { stepsOnThread.clear(); initStepsOnThread.clear(); + for (auto iter : frameData.activePushBuffers) { + iter->MapDevice(); + } + switch (frameData.type) { case GLRRunType::END: EndSubmitFrame(frame); @@ -446,11 +455,6 @@ void GLRenderManager::Run(int frame) { } void GLRenderManager::FlushSync() { - // Need to flush any pushbuffers to VRAM before submitting draw calls. - for (auto iter : frameData_[curFrame_].activePushBuffers) { - iter->Flush(); - } - // TODO: Reset curRenderStep_? int curFrame = curFrame_; FrameData &frameData = frameData_[curFrame]; @@ -532,42 +536,51 @@ GLPushBuffer::~GLPushBuffer() { void GLPushBuffer::Map() { assert(!writePtr_); - // TODO: Even a good old glMapBuffer could actually work well here. - writePtr_ = buffers_[buf_].deviceMemory; + auto &info = buffers_[buf_]; + writePtr_ = info.deviceMemory ? info.deviceMemory : info.localMemory; + // Force alignment. This is needed for PushAligned() to work as expected. + while ((intptr_t)writePtr_ & 15) { + writePtr_++; + } assert(writePtr_); } void GLPushBuffer::Unmap() { assert(writePtr_); - // Here we simply upload the data to the last buffer. - // Might be worth trying with size_ instead of offset_, so the driver can replace - // the whole buffer. At least if it's close. - render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].deviceMemory, false); + if (!buffers_[buf_].deviceMemory) { + // Here we simply upload the data to the last buffer. + // Might be worth trying with size_ instead of offset_, so the driver can replace + // the whole buffer. At least if it's close. + render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].localMemory, false); + } writePtr_ = nullptr; } void GLPushBuffer::Flush() { - render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].deviceMemory, false); - // Here we will submit all the draw calls, with the already known buffer and offsets. - // Might as well reset the write pointer here and start over the current buffer. - writePtr_ = buffers_[buf_].deviceMemory; - offset_ = 0; + // We don't need to do this for device memory. + if (!buffers_[buf_].deviceMemory && writePtr_) { + render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].localMemory, false); + // Here we will submit all the draw calls, with the already known buffer and offsets. + // Might as well reset the write pointer here and start over the current buffer. + writePtr_ = buffers_[buf_].localMemory; + offset_ = 0; + } } bool GLPushBuffer::AddBuffer() { BufInfo info; - info.deviceMemory = new uint8_t[size_]; + info.localMemory = new uint8_t[size_]; info.buffer = render_->CreateBuffer(target_, size_, GL_DYNAMIC_DRAW); buf_ = buffers_.size(); - buffers_.resize(buf_ + 1); - buffers_[buf_] = info; + buffers_.push_back(info); return true; } void GLPushBuffer::Destroy() { for (BufInfo &info : buffers_) { + // This will automatically unmap device memory, if needed. render_->DeleteBuffer(info.buffer); - delete[] info.deviceMemory; + delete[] info.localMemory; } buffers_.clear(); } @@ -617,3 +630,37 @@ size_t GLPushBuffer::GetTotalSize() const { sum += offset_; return sum; } + +void GLPushBuffer::MapDevice() { + for (auto &info : buffers_) { + assert(!info.deviceMemory); + // TODO: Can we use GL_WRITE_ONLY? + info.deviceMemory = (uint8_t *)info.buffer->Map(GL_READ_WRITE); + + if (info.deviceMemory) { + delete[] info.localMemory; + info.localMemory = nullptr; + } else if (!info.localMemory) { + // Somehow it failed, let's dodge crashing. + info.localMemory = new uint8_t[info.buffer->size_]; + } + + assert(info.localMemory || info.deviceMemory); + } + + if (writePtr_) { + // This can happen during a sync. Remap. + writePtr_ = nullptr; + Map(); + } +} + +void GLPushBuffer::UnmapDevice() { + for (auto &info : buffers_) { + if (info.deviceMemory) { + // TODO: Technically this can return false? + info.buffer->Unmap(); + info.deviceMemory = nullptr; + } + } +} diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index c3b473e605..bbf46c65f1 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -138,10 +138,30 @@ public: glDeleteBuffers(1, &buffer); } } + + void *Map(GLenum access) { + glBindBuffer(target_, buffer); + void *p = glMapBuffer(target_, access); + mapped_ = p != nullptr; + return p; + } + + bool Unmap() { + glBindBuffer(target_, buffer); + mapped_ = false; + return glUnmapBuffer(target_) == GL_TRUE; + } + + bool Mapped() { + return mapped_; + } + GLuint buffer = 0; GLuint target_; int size_; + private: + bool mapped_ = false; }; enum class GLRRunType { @@ -747,8 +767,9 @@ private: class GLPushBuffer { public: struct BufInfo { - GLRBuffer *buffer; - uint8_t *deviceMemory; + GLRBuffer *buffer = nullptr; + uint8_t *localMemory = nullptr; + uint8_t *deviceMemory = nullptr; }; public: @@ -835,6 +856,10 @@ public: void Flush(); +protected: + void MapDevice(); + void UnmapDevice(); + private: bool AddBuffer(); void NextBuffer(size_t minSize); @@ -847,4 +872,6 @@ private: size_t size_ = 0; uint8_t *writePtr_ = nullptr; GLuint target_; + + friend class GLRenderManager; }; From edcd2f966a078199a64e375587c846dfe26f7b85 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 11:53:19 -0800 Subject: [PATCH 153/291] GLES: Use buffer range mapping where appropriate. --- ext/native/thin3d/GLRenderManager.cpp | 30 ++++++++++++++++++++++++++- ext/native/thin3d/GLRenderManager.h | 14 ++----------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index d66deb5d4f..57a80d79ec 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -633,9 +633,14 @@ size_t GLPushBuffer::GetTotalSize() const { void GLPushBuffer::MapDevice() { for (auto &info : buffers_) { + if (!info.buffer->buffer) { + // Can't map - no device buffer associated yet. + continue; + } + assert(!info.deviceMemory); // TODO: Can we use GL_WRITE_ONLY? - info.deviceMemory = (uint8_t *)info.buffer->Map(GL_READ_WRITE); + info.deviceMemory = (uint8_t *)info.buffer->Map(GL_READ_WRITE, GL_MAP_WRITE_BIT); if (info.deviceMemory) { delete[] info.localMemory; @@ -664,3 +669,26 @@ void GLPushBuffer::UnmapDevice() { } } } + +void *GLRBuffer::Map(GLenum accessOld, GLbitfield accessNew) { + assert(buffer != 0); + glBindBuffer(target_, buffer); + + void *p; + if (gl_extensions.VersionGEThan(3, 0, 0)) { + p = glMapBufferRange(target_, 0, size_, accessNew); + } else { +#ifndef USING_GLES2 + p = glMapBuffer(target_, accessOld); +#endif + } + + mapped_ = p != nullptr; + return p; +} + +bool GLRBuffer::Unmap() { + glBindBuffer(target_, buffer); + mapped_ = false; + return glUnmapBuffer(target_) == GL_TRUE; +} diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index bbf46c65f1..270dcb243b 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -139,18 +139,8 @@ public: } } - void *Map(GLenum access) { - glBindBuffer(target_, buffer); - void *p = glMapBuffer(target_, access); - mapped_ = p != nullptr; - return p; - } - - bool Unmap() { - glBindBuffer(target_, buffer); - mapped_ = false; - return glUnmapBuffer(target_) == GL_TRUE; - } + void *Map(GLenum accessOld, GLbitfield accessNew); + bool Unmap(); bool Mapped() { return mapped_; From 7179e408da8ecca80233ca954bcef0ef2a1eedda Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 12:34:01 -0800 Subject: [PATCH 154/291] GLES: Free localMemory later. It was still in use sometimes as of MapDevice(), so this is safer. --- ext/native/thin3d/GLRenderManager.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 57a80d79ec..7c6bac029b 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -611,6 +611,14 @@ void GLPushBuffer::NextBuffer(size_t minSize) { void GLPushBuffer::Defragment() { if (buffers_.size() <= 1) { + // Let's take this chance to jetison localMemory we don't need. + for (auto &info : buffers_) { + if (info.deviceMemory) { + delete[] info.localMemory; + info.localMemory = nullptr; + } + } + return; } @@ -642,10 +650,7 @@ void GLPushBuffer::MapDevice() { // TODO: Can we use GL_WRITE_ONLY? info.deviceMemory = (uint8_t *)info.buffer->Map(GL_READ_WRITE, GL_MAP_WRITE_BIT); - if (info.deviceMemory) { - delete[] info.localMemory; - info.localMemory = nullptr; - } else if (!info.localMemory) { + if (!info.deviceMemory && !info.localMemory) { // Somehow it failed, let's dodge crashing. info.localMemory = new uint8_t[info.buffer->size_]; } From 20b532fc71c79a79d70c10a4bfac9908e061d16b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 13:14:28 -0800 Subject: [PATCH 155/291] GLES: Use buffer storage and explicit flush. This is just as fast as using glMapBufferRange on desktop. --- ext/native/gfx_es2/gl3stub.c | 6 ++++ ext/native/gfx_es2/gl3stub.h | 9 +++++- ext/native/gfx_es2/gpu_features.cpp | 4 ++- ext/native/gfx_es2/gpu_features.h | 2 ++ ext/native/thin3d/GLRenderManager.cpp | 45 ++++++++++++++++++++++----- ext/native/thin3d/GLRenderManager.h | 2 ++ 6 files changed, 59 insertions(+), 9 deletions(-) diff --git a/ext/native/gfx_es2/gl3stub.c b/ext/native/gfx_es2/gl3stub.c index f891c11fa9..57fe835761 100644 --- a/ext/native/gfx_es2/gl3stub.c +++ b/ext/native/gfx_es2/gl3stub.c @@ -135,6 +135,9 @@ GLboolean gl3stubInit() { FIND_PROC(glGetProgramResourceLocationIndexEXT); FIND_PROC(glGetFragDataIndexEXT); + /* EXT_buffer_storage */ + FIND_PROC(glBufferStorageEXT); + /* OES_copy_image, etc. */ FIND_PROC(glCopyImageSubDataOES); @@ -366,6 +369,9 @@ GL_APICALL void (* GL_APIENTRY glBindFragDataLocationEXT) (GLuint prog GL_APICALL GLint (* GL_APIENTRY glGetProgramResourceLocationIndexEXT) (GLuint program, GLenum programInterface, const GLchar *name); GL_APICALL GLint (* GL_APIENTRY glGetFragDataIndexEXT) (GLuint program, const GLchar *name); +/* EXT_buffer_storage */ +GL_APICALL void (* GL_APIENTRY glBufferStorageEXT) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); + /* OES_copy_image, etc. */ GL_APICALL void (* GL_APIENTRY glCopyImageSubDataOES) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); diff --git a/ext/native/gfx_es2/gl3stub.h b/ext/native/gfx_es2/gl3stub.h index acc630fa0e..080db197cf 100644 --- a/ext/native/gfx_es2/gl3stub.h +++ b/ext/native/gfx_es2/gl3stub.h @@ -260,6 +260,10 @@ typedef struct __GLsync *GLsync; #define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 #define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 #define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_MAP_PERSISTENT_BIT_EXT 0x0040 +#define GL_MAP_COHERENT_BIT_EXT 0x0080 +#define GL_DYNAMIC_STORAGE_BIT_EXT 0x0100 +#define GL_CLIENT_STORAGE_BIT_EXT 0x0200 #define GL_RG 0x8227 #define GL_RG_INTEGER 0x8228 #define GL_R8 0x8229 @@ -500,9 +504,12 @@ extern GL_APICALL void (* GL_APIENTRY glBindFragDataLocationEXT) (GLui extern GL_APICALL GLint (* GL_APIENTRY glGetProgramResourceLocationIndexEXT) (GLuint program, GLenum programInterface, const GLchar *name); extern GL_APICALL GLint (* GL_APIENTRY glGetFragDataIndexEXT) (GLuint program, const GLchar *name); +/* EXT_buffer_storage */ +extern GL_APICALL void (* GL_APIENTRY glBufferStorageEXT) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); + /* OES_copy_image, etc. */ extern GL_APICALL void (* GL_APIENTRY glCopyImageSubDataOES) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); - + #endif // IOS #ifdef __cplusplus diff --git a/ext/native/gfx_es2/gpu_features.cpp b/ext/native/gfx_es2/gpu_features.cpp index 69ffa7c897..1eb2392cc4 100644 --- a/ext/native/gfx_es2/gpu_features.cpp +++ b/ext/native/gfx_es2/gpu_features.cpp @@ -299,6 +299,7 @@ void CheckGLExtensions() { gl_extensions.OES_copy_image = strstr(extString, "GL_OES_copy_image") != 0; gl_extensions.EXT_copy_image = strstr(extString, "GL_EXT_copy_image") != 0; gl_extensions.ARB_copy_image = strstr(extString, "GL_ARB_copy_image") != 0; + gl_extensions.ARB_buffer_storage = strstr(extString, "GL_ARB_buffer_storage") != 0; gl_extensions.ARB_vertex_array_object = strstr(extString, "GL_ARB_vertex_array_object") != 0; gl_extensions.ARB_texture_float = strstr(extString, "GL_ARB_texture_float") != 0; gl_extensions.EXT_texture_filter_anisotropic = strstr(extString, "GL_EXT_texture_filter_anisotropic") != 0; @@ -317,6 +318,7 @@ void CheckGLExtensions() { gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; gl_extensions.ARM_shader_framebuffer_fetch = strstr(extString, "GL_ARM_shader_framebuffer_fetch") != 0; gl_extensions.OES_texture_float = strstr(extString, "GL_OES_texture_float") != 0; + gl_extensions.EXT_buffer_storage = strstr(extString, "GL_EXT_buffer_storage") != 0; #if defined(__ANDROID__) // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. @@ -458,7 +460,7 @@ void CheckGLExtensions() { // ARB_vertex_attrib_binding = true; } if (gl_extensions.VersionGEThan(4, 4)) { - // ARB_buffer_storage = true; + gl_extensions.ARB_buffer_storage = true; } } diff --git a/ext/native/gfx_es2/gpu_features.h b/ext/native/gfx_es2/gpu_features.h index b12b406eee..c3a7a9161d 100644 --- a/ext/native/gfx_es2/gpu_features.h +++ b/ext/native/gfx_es2/gpu_features.h @@ -61,6 +61,7 @@ struct GLExtensions { bool ARB_vertex_array_object; bool ARB_texture_float; bool ARB_draw_instanced; + bool ARB_buffer_storage; // EXT bool EXT_swap_control_tear; @@ -75,6 +76,7 @@ struct GLExtensions { bool EXT_texture_filter_anisotropic; bool PBO_EXT; bool EXT_draw_instanced; + bool EXT_buffer_storage; // NV bool NV_shader_framebuffer_fetch; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 7c6bac029b..c2702fe9c3 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -542,6 +542,7 @@ void GLPushBuffer::Map() { while ((intptr_t)writePtr_ & 15) { writePtr_++; } + info.flushOffset = 0; assert(writePtr_); } @@ -552,18 +553,37 @@ void GLPushBuffer::Unmap() { // Might be worth trying with size_ instead of offset_, so the driver can replace // the whole buffer. At least if it's close. render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].localMemory, false); + } else { + buffers_[buf_].flushOffset = offset_; } writePtr_ = nullptr; } void GLPushBuffer::Flush() { - // We don't need to do this for device memory. + // Must be called from the render thread. + buffers_[buf_].flushOffset = offset_; if (!buffers_[buf_].deviceMemory && writePtr_) { - render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].localMemory, false); + auto &info = buffers_[buf_]; + glBindBuffer(target_, info.buffer->buffer); + glBufferSubData(target_, 0, info.flushOffset, info.localMemory); + // Here we will submit all the draw calls, with the already known buffer and offsets. // Might as well reset the write pointer here and start over the current buffer. - writePtr_ = buffers_[buf_].localMemory; + writePtr_ = info.localMemory; offset_ = 0; + info.flushOffset = 0; + } + + // For device memory, we flush all buffers here. + if (gl_extensions.VersionGEThan(3, 0, 0)) { + for (auto &info : buffers_) { + if (info.flushOffset == 0 || !info.deviceMemory) + continue; + + glBindBuffer(target_, info.buffer->buffer); + glFlushMappedBufferRange(target_, 0, info.flushOffset); + info.flushOffset = 0; + } } } @@ -648,7 +668,7 @@ void GLPushBuffer::MapDevice() { assert(!info.deviceMemory); // TODO: Can we use GL_WRITE_ONLY? - info.deviceMemory = (uint8_t *)info.buffer->Map(GL_READ_WRITE, GL_MAP_WRITE_BIT); + info.deviceMemory = (uint8_t *)info.buffer->Map(GL_READ_WRITE, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); if (!info.deviceMemory && !info.localMemory) { // Somehow it failed, let's dodge crashing. @@ -679,12 +699,23 @@ void *GLRBuffer::Map(GLenum accessOld, GLbitfield accessNew) { assert(buffer != 0); glBindBuffer(target_, buffer); - void *p; - if (gl_extensions.VersionGEThan(3, 0, 0)) { + void *p = nullptr; + if (gl_extensions.ARB_buffer_storage || gl_extensions.EXT_buffer_storage) { + if (!hasStorage_) { +#ifdef USING_GLES2 + glBufferStorageEXT(target_, size_, nullptr, GL_MAP_WRITE_BIT); +#else + glBufferStorage(target_, size_, nullptr, GL_MAP_WRITE_BIT); +#endif + hasStorage_ = true; + } + p = glMapBufferRange(target_, 0, size_, accessNew); + } else if (gl_extensions.VersionGEThan(3, 0, 0)) { + // GLES3 or desktop 3. p = glMapBufferRange(target_, 0, size_, accessNew); } else { #ifndef USING_GLES2 - p = glMapBuffer(target_, accessOld); + p = glMapBuffer(target_, accessOld); #endif } diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 270dcb243b..b45e401f6e 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -152,6 +152,7 @@ public: private: bool mapped_ = false; + bool hasStorage_ = false; }; enum class GLRRunType { @@ -760,6 +761,7 @@ public: GLRBuffer *buffer = nullptr; uint8_t *localMemory = nullptr; uint8_t *deviceMemory = nullptr; + size_t flushOffset = 0; }; public: From 5f1cd19687a54f399ce8a81f98cc3ff76bc395af Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 13:17:08 -0800 Subject: [PATCH 156/291] GLES: Android buildfix. --- ext/native/thin3d/GLRenderManager.cpp | 14 +++++++------- ext/native/thin3d/GLRenderManager.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index c2702fe9c3..0a906b241b 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -668,7 +668,7 @@ void GLPushBuffer::MapDevice() { assert(!info.deviceMemory); // TODO: Can we use GL_WRITE_ONLY? - info.deviceMemory = (uint8_t *)info.buffer->Map(GL_READ_WRITE, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); + info.deviceMemory = (uint8_t *)info.buffer->Map(GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); if (!info.deviceMemory && !info.localMemory) { // Somehow it failed, let's dodge crashing. @@ -695,7 +695,7 @@ void GLPushBuffer::UnmapDevice() { } } -void *GLRBuffer::Map(GLenum accessOld, GLbitfield accessNew) { +void *GLRBuffer::Map(GLbitfield access) { assert(buffer != 0); glBindBuffer(target_, buffer); @@ -703,19 +703,19 @@ void *GLRBuffer::Map(GLenum accessOld, GLbitfield accessNew) { if (gl_extensions.ARB_buffer_storage || gl_extensions.EXT_buffer_storage) { if (!hasStorage_) { #ifdef USING_GLES2 - glBufferStorageEXT(target_, size_, nullptr, GL_MAP_WRITE_BIT); + glBufferStorageEXT(target_, size_, nullptr, access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); #else - glBufferStorage(target_, size_, nullptr, GL_MAP_WRITE_BIT); + glBufferStorage(target_, size_, nullptr, access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); #endif hasStorage_ = true; } - p = glMapBufferRange(target_, 0, size_, accessNew); + p = glMapBufferRange(target_, 0, size_, access); } else if (gl_extensions.VersionGEThan(3, 0, 0)) { // GLES3 or desktop 3. - p = glMapBufferRange(target_, 0, size_, accessNew); + p = glMapBufferRange(target_, 0, size_, access); } else { #ifndef USING_GLES2 - p = glMapBuffer(target_, accessOld); + p = glMapBuffer(target_, GL_READ_WRITE); #endif } diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index b45e401f6e..f9b30936fb 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -139,7 +139,7 @@ public: } } - void *Map(GLenum accessOld, GLbitfield accessNew); + void *Map(GLbitfield access); bool Unmap(); bool Mapped() { From be0ab583655b93f4cc4f867621a483a2be3e6701 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 14:38:36 -0800 Subject: [PATCH 157/291] GLES: iOS buildfix. --- ext/native/thin3d/GLRenderManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 0a906b241b..4a96479669 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -701,6 +701,7 @@ void *GLRBuffer::Map(GLbitfield access) { void *p = nullptr; if (gl_extensions.ARB_buffer_storage || gl_extensions.EXT_buffer_storage) { +#ifndef IOS if (!hasStorage_) { #ifdef USING_GLES2 glBufferStorageEXT(target_, size_, nullptr, access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); @@ -709,6 +710,7 @@ void *GLRBuffer::Map(GLbitfield access) { #endif hasStorage_ = true; } +#endif p = glMapBufferRange(target_, 0, size_, access); } else if (gl_extensions.VersionGEThan(3, 0, 0)) { // GLES3 or desktop 3. From 17bcb080f08f4a18efa3e45a50e93571e57deaeb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Feb 2018 15:19:16 -0800 Subject: [PATCH 158/291] GLES: Fix shutdown while stepping. --- Windows/EmuThread.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 27a34fcc7b..03a8124725 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -59,6 +59,7 @@ void MainThread_Start(bool separateEmuThread) { void MainThread_Stop() { // Already stopped? UpdateUIState(UISTATE_EXIT); + Core_Stop(); mainThread.join(); } From 1b9c2f26f93cbf3880760c6bef8fe045bbf56b25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Feb 2018 11:46:19 +0100 Subject: [PATCH 159/291] Whitelist mapbuffer usage to NVIDIA only (should maybe add Qualcomm too), it's murder on Mali --- ext/SPIRV-Cross | 2 +- ext/armips | 2 +- ext/glslang | 2 +- ext/native/gfx_es2/gpu_features.cpp | 6 ++++++ ext/native/gfx_es2/gpu_features.h | 1 + ext/native/thin3d/GLRenderManager.cpp | 4 ++-- 6 files changed, 12 insertions(+), 5 deletions(-) diff --git a/ext/SPIRV-Cross b/ext/SPIRV-Cross index 90966d50f5..6381b2ff9c 160000 --- a/ext/SPIRV-Cross +++ b/ext/SPIRV-Cross @@ -1 +1 @@ -Subproject commit 90966d50f57608587bafd95b4e345b02b814754a +Subproject commit 6381b2ff9c0d975af8fd2974c97aa12a69ab6cc6 diff --git a/ext/armips b/ext/armips index 8b4cadaf62..770365d44d 160000 --- a/ext/armips +++ b/ext/armips @@ -1 +1 @@ -Subproject commit 8b4cadaf62d7de42d374056fc6aafc555f2bc7dc +Subproject commit 770365d44df35d6e675c58bb2a774ca412278ef5 diff --git a/ext/glslang b/ext/glslang index 2edde6665d..b16f7e6819 160000 --- a/ext/glslang +++ b/ext/glslang @@ -1 +1 @@ -Subproject commit 2edde6665d9a56ead5ea0e55b4e64d9a803e6164 +Subproject commit b16f7e6819267e57c3c244808d1981f0ce34acbc diff --git a/ext/native/gfx_es2/gpu_features.cpp b/ext/native/gfx_es2/gpu_features.cpp index 1eb2392cc4..966781cc75 100644 --- a/ext/native/gfx_es2/gpu_features.cpp +++ b/ext/native/gfx_es2/gpu_features.cpp @@ -77,6 +77,12 @@ void ProcessGPUFeatures() { } gl_extensions.bugs |= BUG_PVR_GENMIPMAP_HEIGHT_GREATER; } + + // TODO: Make this check more lenient. Disabled for all right now + // because it murders performance on Mali. + if (gl_extensions.gpuVendor != GPU_VENDOR_NVIDIA) { + gl_extensions.bugs |= BUG_ANY_MAP_BUFFER_RANGE_SLOW; + } } // http://stackoverflow.com/questions/16147700/opengl-es-using-tegra-specific-extensions-gl-ext-texture-array diff --git a/ext/native/gfx_es2/gpu_features.h b/ext/native/gfx_es2/gpu_features.h index c3a7a9161d..b26e923b55 100644 --- a/ext/native/gfx_es2/gpu_features.h +++ b/ext/native/gfx_es2/gpu_features.h @@ -23,6 +23,7 @@ enum { BUG_PVR_SHADER_PRECISION_BAD = 2, BUG_PVR_SHADER_PRECISION_TERRIBLE = 4, BUG_PVR_GENMIPMAP_HEIGHT_GREATER = 8, + BUG_ANY_MAP_BUFFER_RANGE_SLOW = 16, }; // Extensions to look at using: diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 4a96479669..2c3f0b1b58 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -712,10 +712,10 @@ void *GLRBuffer::Map(GLbitfield access) { } #endif p = glMapBufferRange(target_, 0, size_, access); - } else if (gl_extensions.VersionGEThan(3, 0, 0)) { + } else if (gl_extensions.VersionGEThan(3, 0, 0) && !(gl_extensions.bugs & BUG_ANY_MAP_BUFFER_RANGE_SLOW)) { // GLES3 or desktop 3. p = glMapBufferRange(target_, 0, size_, access); - } else { + } else if (!(gl_extensions.bugs & BUG_ANY_MAP_BUFFER_RANGE_SLOW)) { #ifndef USING_GLES2 p = glMapBuffer(target_, GL_READ_WRITE); #endif From 9e75358cd0f145ef91d752335c707c7b44297823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Feb 2018 11:50:55 +0100 Subject: [PATCH 160/291] Oops, didn't mean to update the submodules backwards (remains from a bisect) --- ext/SPIRV-Cross | 2 +- ext/armips | 2 +- ext/glslang | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/SPIRV-Cross b/ext/SPIRV-Cross index 6381b2ff9c..90966d50f5 160000 --- a/ext/SPIRV-Cross +++ b/ext/SPIRV-Cross @@ -1 +1 @@ -Subproject commit 6381b2ff9c0d975af8fd2974c97aa12a69ab6cc6 +Subproject commit 90966d50f57608587bafd95b4e345b02b814754a diff --git a/ext/armips b/ext/armips index 770365d44d..8b4cadaf62 160000 --- a/ext/armips +++ b/ext/armips @@ -1 +1 @@ -Subproject commit 770365d44df35d6e675c58bb2a774ca412278ef5 +Subproject commit 8b4cadaf62d7de42d374056fc6aafc555f2bc7dc diff --git a/ext/glslang b/ext/glslang index b16f7e6819..2edde6665d 160000 --- a/ext/glslang +++ b/ext/glslang @@ -1 +1 @@ -Subproject commit b16f7e6819267e57c3c244808d1981f0ce34acbc +Subproject commit 2edde6665d9a56ead5ea0e55b4e64d9a803e6164 From 88e822915918372f22f1d27a39ece0e56e75ee5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Feb 2018 14:01:23 +0100 Subject: [PATCH 161/291] GL: Need to recompile postshaders on Resized() (which is a bit of a misnomer) --- GPU/GLES/FramebufferManagerGLES.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 351579744f..eb027bf453 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -792,6 +792,9 @@ void FramebufferManagerGLES::Resized() { DestroyAllFBOs(); } + // Might have a new post shader - let's compile it. + CompilePostShader(); + // render_->SetLineWidth(renderWidth_ / 480.0f); } From 7421f2aff6c84d3064462f45b91f11e83f385731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Feb 2018 14:10:54 +0100 Subject: [PATCH 162/291] Postprocessing: Fix bug where scissor cut off the image if render resolution > display resolution --- GPU/Common/FramebufferCommon.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 03c0aad4c8..fd2bf19ec4 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -991,7 +991,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { int fbo_w, fbo_h; draw_->GetFramebufferDimensions(extraFBOs_[0], &fbo_w, &fbo_h); SetViewport2D(0, 0, fbo_w, fbo_h); - draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_); + draw_->SetScissorRect(0, 0, fbo_w, fbo_h); shaderManager_->DirtyLastShader(); // dirty lastShader_ PostShaderUniforms uniforms{}; CalculatePostShaderUniforms(vfb->bufferWidth, vfb->bufferHeight, renderWidth_, renderHeight_, &uniforms); @@ -999,8 +999,8 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { DrawTextureFlags flags = g_Config.iBufFilter == SCALE_LINEAR ? DRAWTEX_LINEAR : DRAWTEX_NEAREST; DrawActiveTexture(0, 0, fbo_w, fbo_h, fbo_w, fbo_h, 0.0f, 0.0f, 1.0f, 1.0f, ROTATION_LOCKED_HORIZONTAL, flags); + draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_); draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); - SetViewport2D(0, 0, pixelWidth_, pixelHeight_); // Use the extra FBO, with applied post-processing shader, as a texture. // fbo_bind_as_texture(extraFBOs_[0], FB_COLOR_BIT, 0); From 926b3873df75ffbf72d43813232df658e4d78a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Feb 2018 17:47:31 +0100 Subject: [PATCH 163/291] Fix issue with Vulkan task switching and resolution changes on Android. --- android/jni/app-android.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 747629bde6..1e54500f0f 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -448,7 +448,7 @@ retry: case (int)GPUBackend::VULKAN: ILOG("NativeApp.init() -- creating Vulkan context"); useCPUThread = false; // The Vulkan render manager manages its own thread. - graphicsContext = new AndroidVulkanContext(); + // We create and destroy the Vulkan graphics context in the "EGL" thread. break; default: ELOG("NativeApp.init(): iGPUBackend %d not supported. Switching to OpenGL.", (int)g_Config.iGPUBackend); @@ -931,6 +931,12 @@ retry: int tries = 0; + _assert_msg_(G3D, !graphicsContext, "Graphics context already exists entering runEGLRenderLoop - this is wrong."); + + if (vulkan) { + graphicsContext = new AndroidVulkanContext(); + } + if (!graphicsContext->InitFromRenderThread(wnd, desiredBackbufferSizeX, desiredBackbufferSizeY, backbuffer_format, androidVersion)) { ELOG("Failed to initialize graphics context."); From d61fd5f6a6cab1901a48a57a50a49e2956f66b96 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Feb 2018 12:26:00 -0800 Subject: [PATCH 164/291] TexCache: Decimate CLUT variants more often. When creating a new texture, we determine if it has CLUT variants and decimate more often. --- GPU/Common/TextureCacheCommon.cpp | 22 +++++++++++++++++++++- GPU/Common/TextureCacheCommon.h | 3 +-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 75f9a5d14c..062cbf9224 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -46,6 +46,8 @@ #define TEXTURE_KILL_AGE_LOWMEM 60 // Not used in lowmem mode. #define TEXTURE_SECOND_KILL_AGE 100 +// Used when there are multiple CLUT variants of a texture. +#define TEXTURE_KILL_AGE_CLUT 12 // Try to be prime to other decimation intervals. #define TEXCACHE_DECIMATION_INTERVAL 13 @@ -454,6 +456,22 @@ void TextureCacheCommon::SetTexture(bool force) { entry->status = TexCacheEntry::STATUS_UNRELIABLE; } + if (hasClut && clutRenderAddress_ == 0xFFFFFFFF) { + const u64 cachekeyMin = (u64)(texaddr & 0x3FFFFFFF) << 32; + const u64 cachekeyMax = cachekeyMin + (1ULL << 32); + bool found = false; + for (auto it = cache_.lower_bound(cachekeyMin), end = cache_.upper_bound(cachekeyMax); it != end; ++it) { + if (it->second->cluthash != entry->cluthash) { + it->second->status |= TexCacheEntry::STATUS_CLUT_VARIANTS; + found = true; + } + } + + if (found) { + entry->status |= TexCacheEntry::STATUS_CLUT_VARIANTS; + } + } + nextNeedsChange_ = false; } @@ -505,8 +523,10 @@ void TextureCacheCommon::Decimate() { const u32 had = cacheSizeEstimate_; ForgetLastTexture(); - int killAge = lowMemoryMode_ ? TEXTURE_KILL_AGE_LOWMEM : TEXTURE_KILL_AGE; + int killAgeBase = lowMemoryMode_ ? TEXTURE_KILL_AGE_LOWMEM : TEXTURE_KILL_AGE; for (TexCache::iterator iter = cache_.begin(); iter != cache_.end(); ) { + bool hasClut = (iter->second->status & TexCacheEntry::STATUS_CLUT_VARIANTS) != 0; + int killAge = hasClut ? TEXTURE_KILL_AGE_CLUT : killAgeBase; if (iter->second->lastFrame + killAge < gpuStats.numFlips) { DeleteTexture(iter++); } else { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 1bc16a2541..0c3e626545 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -108,8 +108,7 @@ struct TexCacheEntry { STATUS_ALPHA_FULL = 0x00, // Has no alpha channel, or always full alpha. STATUS_ALPHA_MASK = 0x04, - // 0x08 free. - + STATUS_CLUT_VARIANTS = 0x08, // Has multiple CLUT variants. STATUS_CHANGE_FREQUENT = 0x10, // Changes often (less than 6 frames in between.) STATUS_CLUT_RECHECK = 0x20, // Another texture with same addr had a hashfail. STATUS_DEPALETTIZE = 0x40, // Needs to go through a depalettize pass. From e97046da4e9c057af46849e7c9c34113aabaf944 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Feb 2018 12:29:14 -0800 Subject: [PATCH 165/291] TexCache: Decimate aggressively with many variants. It should be safe to decimate after fewer frames with a threshold like this. --- GPU/Common/TextureCacheCommon.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 062cbf9224..51703e3ecd 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -47,7 +47,9 @@ // Not used in lowmem mode. #define TEXTURE_SECOND_KILL_AGE 100 // Used when there are multiple CLUT variants of a texture. -#define TEXTURE_KILL_AGE_CLUT 12 +#define TEXTURE_KILL_AGE_CLUT 6 + +#define TEXTURE_CLUT_VARIANTS_MIN 6 // Try to be prime to other decimation intervals. #define TEXCACHE_DECIMATION_INTERVAL 13 @@ -459,15 +461,17 @@ void TextureCacheCommon::SetTexture(bool force) { if (hasClut && clutRenderAddress_ == 0xFFFFFFFF) { const u64 cachekeyMin = (u64)(texaddr & 0x3FFFFFFF) << 32; const u64 cachekeyMax = cachekeyMin + (1ULL << 32); - bool found = false; + + int found = 0; for (auto it = cache_.lower_bound(cachekeyMin), end = cache_.upper_bound(cachekeyMax); it != end; ++it) { - if (it->second->cluthash != entry->cluthash) { - it->second->status |= TexCacheEntry::STATUS_CLUT_VARIANTS; - found = true; - } + found++; } - if (found) { + if (found >= TEXTURE_CLUT_VARIANTS_MIN) { + for (auto it = cache_.lower_bound(cachekeyMin), end = cache_.upper_bound(cachekeyMax); it != end; ++it) { + it->second->status |= TexCacheEntry::STATUS_CLUT_VARIANTS; + } + entry->status |= TexCacheEntry::STATUS_CLUT_VARIANTS; } } From 438951f84412e002b169b97dea60601f63a27acb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Feb 2018 19:03:31 -0800 Subject: [PATCH 166/291] GLES: Properly free when upscaling textures. Oops. Fixes crash introduced by #10603. --- GPU/GLES/TextureCacheGLES.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 1c1ff3551d..cfa0ab0cb0 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -788,7 +788,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(w * scaleFactor * h * scaleFactor * 4, 16); scaler.ScaleAlways((u32 *)rearrange, (u32 *)pixelData, dstFmt, w, h, scaleFactor); pixelData = rearrange; - delete [] finalBuf; + FreeAlignedMemory(finalBuf); } if (replacer_.Enabled()) { From ecd1a04e4470e23b8bea03d17b977fe6aba935b3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 19 Feb 2018 09:02:22 -0800 Subject: [PATCH 167/291] GLES: Fix unpack misalignment, Qt debugger freeing. We no longer use unpack, so we should always decode to w not bufw. --- GPU/GLES/TextureCacheGLES.cpp | 68 ++++++++++++++--------------------- GPU/GLES/TextureCacheGLES.h | 3 -- 2 files changed, 26 insertions(+), 45 deletions(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index cfa0ab0cb0..0430decbf1 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -696,29 +696,6 @@ GLenum TextureCacheGLES::GetDestFormat(GETextureFormat format, GEPaletteFormat c } } -u8 *TextureCacheGLES::DecodeTextureLevelOld(GETextureFormat format, GEPaletteFormat clutformat, int level, GLenum dstFmt, int scaleFactor, int *bufwout) { - void *finalBuf = nullptr; - u32 texaddr = gstate.getTextureAddress(level); - int bufw = GetTextureBufw(level, texaddr, format); - if (bufwout) - *bufwout = bufw; - - int w = gstate.getTextureWidth(level); - int h = gstate.getTextureHeight(level); - - int decPitch = 0; - int pixelSize = dstFmt == GL_UNSIGNED_BYTE ? 4 : 2; - if (!(scaleFactor == 1 && gstate_c.Supports(GPU_SUPPORTS_UNPACK_SUBIMAGE)) && w != bufw) { - decPitch = w * pixelSize; - } else { - decPitch = bufw * pixelSize; - } - - uint8_t *texBuf = (uint8_t *)AllocateAlignedMemory(std::max(w, bufw) * h * pixelSize, 16); - DecodeTextureLevel(texBuf, decPitch, format, clutformat, texaddr, level, bufw, true, false, false); - return texBuf; -} - TexCacheEntry::TexStatus TextureCacheGLES::CheckAlpha(const uint8_t *pixelData, GLenum dstFmt, int stride, int w, int h) { CheckAlphaResult res; switch (dstFmt) { @@ -766,15 +743,19 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r PROFILE_THIS_SCOPE("decodetex"); GEPaletteFormat clutformat = gstate.getClutPaletteFormat(); - int bufw; - uint8_t *finalBuf = DecodeTextureLevelOld(GETextureFormat(entry.format), clutformat, level, dstFmt, scaleFactor, &bufw); - if (!finalBuf) { - return; - } + u32 texaddr = gstate.getTextureAddress(level); + int bufw = GetTextureBufw(level, texaddr, GETextureFormat(entry.format)); + int w = gstate.getTextureWidth(level); + int h = gstate.getTextureHeight(level); + + int pixelSize = dstFmt == GL_UNSIGNED_BYTE ? 4 : 2; + int decPitch = w * pixelSize; + + pixelData = (uint8_t *)AllocateAlignedMemory(decPitch * h * pixelSize, 16); + DecodeTextureLevel(pixelData, decPitch, GETextureFormat(entry.format), clutformat, texaddr, level, bufw, true, false, false); // Textures are always aligned to 16 bytes bufw, so this could safely be 4 always. texByteAlign = dstFmt == GL_UNSIGNED_BYTE ? 4 : 2; - pixelData = finalBuf; // We check before scaling since scaling shouldn't invent alpha from a full alpha texture. if ((entry.status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) { @@ -787,8 +768,8 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r if (scaleFactor > 1) { uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(w * scaleFactor * h * scaleFactor * 4, 16); scaler.ScaleAlways((u32 *)rearrange, (u32 *)pixelData, dstFmt, w, h, scaleFactor); + FreeAlignedMemory(pixelData); pixelData = rearrange; - FreeAlignedMemory(finalBuf); } if (replacer_.Enabled()) { @@ -844,16 +825,17 @@ bool TextureCacheGLES::DecodeTexture(u8* output, const GPUgstate &state) { int w = gstate.getTextureWidth(level); int h = gstate.getTextureHeight(level); - void *finalBuf = DecodeTextureLevelOld(format, clutformat, level, dstFmt, 1); - if (finalBuf == NULL) { - return false; - } + int pixelSize = dstFmt == GL_UNSIGNED_BYTE ? 4 : 2; + int decPitch = w * pixelSize; + + void *finalBuf = AllocateAlignedMemory(decPitch * h * pixelSize, 16); + DecodeTextureLevel((uint8_t *)finalBuf, decPitch, format, clutformat, texaddr, level, bufw, true, false, false); switch (dstFmt) { case GL_UNSIGNED_SHORT_4_4_4_4: for (int y = 0; y < h; y++) - for (int x = 0; x < bufw; x++) { - u32 val = ((u16*)finalBuf)[y*bufw + x]; + for (int x = 0; x < w; x++) { + u32 val = ((u16*)finalBuf)[y*w + x]; u32 r = ((val>>12) & 0xF) * 17; u32 g = ((val>> 8) & 0xF) * 17; u32 b = ((val>> 4) & 0xF) * 17; @@ -864,8 +846,8 @@ bool TextureCacheGLES::DecodeTexture(u8* output, const GPUgstate &state) { case GL_UNSIGNED_SHORT_5_5_5_1: for (int y = 0; y < h; y++) - for (int x = 0; x < bufw; x++) { - u32 val = ((u16*)finalBuf)[y*bufw + x]; + for (int x = 0; x < w; x++) { + u32 val = ((u16*)finalBuf)[y*w + x]; u32 r = Convert5To8((val>>11) & 0x1F); u32 g = Convert5To8((val>> 6) & 0x1F); u32 b = Convert5To8((val>> 1) & 0x1F); @@ -876,8 +858,8 @@ bool TextureCacheGLES::DecodeTexture(u8* output, const GPUgstate &state) { case GL_UNSIGNED_SHORT_5_6_5: for (int y = 0; y < h; y++) - for (int x = 0; x < bufw; x++) { - u32 val = ((u16*)finalBuf)[y*bufw + x]; + for (int x = 0; x < w; x++) { + u32 val = ((u16*)finalBuf)[y*w + x]; u32 a = 0xFF; u32 r = Convert5To8((val>>11) & 0x1F); u32 g = Convert6To8((val>> 5) & 0x3F); @@ -888,13 +870,15 @@ bool TextureCacheGLES::DecodeTexture(u8* output, const GPUgstate &state) { default: for (int y = 0; y < h; y++) - for (int x = 0; x < bufw; x++) { - u32 val = ((u32*)finalBuf)[y*bufw + x]; + for (int x = 0; x < w; x++) { + u32 val = ((u32*)finalBuf)[y*w + x]; ((u32*)output)[y*w + x] = ((val & 0xFF000000)) | ((val & 0x00FF0000)>>16) | ((val & 0x0000FF00)) | ((val & 0x000000FF)<<16); } break; } + FreeAlignedMemory(finalBuf); + gstate = oldState; return true; } diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 2d415c599a..eb81e44663 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -81,9 +81,6 @@ private: void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, bool replaceImages, int scaleFactor, GLenum dstFmt); GLenum GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; - // Caller owns the returned buffer. Delete[]. - u8 *DecodeTextureLevelOld(GETextureFormat format, GEPaletteFormat clutformat, int level, GLenum dstFmt, int scaleFactor, int *bufw = 0); - TexCacheEntry::TexStatus CheckAlpha(const uint8_t *pixelData, GLenum dstFmt, int stride, int w, int h); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override; void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; From 4b8d8c875d35aa101e1a425445474ca82005bd56 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 19 Feb 2018 09:09:35 -0800 Subject: [PATCH 168/291] Qt: Remove old texture debug API. No one's testing it and it's not the best way. We have a better implemented API and should use it instead. --- GPU/D3D11/GPU_D3D11.h | 3 -- GPU/D3D11/TextureCacheD3D11.cpp | 5 -- GPU/D3D11/TextureCacheD3D11.h | 3 -- GPU/Directx9/GPU_DX9.h | 3 -- GPU/Directx9/TextureCacheDX9.cpp | 6 --- GPU/Directx9/TextureCacheDX9.h | 3 -- GPU/GLES/GPU_GLES.h | 3 -- GPU/GLES/TextureCacheGLES.cpp | 79 ------------------------------ GPU/GLES/TextureCacheGLES.h | 3 -- GPU/GPUCommon.h | 3 -- GPU/GPUInterface.h | 1 - GPU/Vulkan/GPU_Vulkan.h | 3 -- Qt/Debugger/debugger_memorytex.cpp | 12 +---- 13 files changed, 1 insertion(+), 126 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 9d7ff6bc59..f2dea31c61 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -50,9 +50,6 @@ public: void DoState(PointerWrap &p) override; void ClearShaderCache() override; - bool DecodeTexture(u8 *dest, const GPUgstate &state) override { - return false; - } bool FramebufferDirty() override; bool FramebufferReallyDirty() override; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index fc12d417db..dfcd8e9334 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -769,11 +769,6 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture & FreeAlignedMemory(mapData); } -bool TextureCacheD3D11::DecodeTexture(u8 *output, const GPUgstate &state) { - OutputDebugStringA("TextureCache::DecodeTexture : FixMe\r\n"); - return true; -} - bool TextureCacheD3D11::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) { SetTexture(false); if (!nextTexture_) diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index c7fdc9899d..c20ed762a9 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -57,9 +57,6 @@ public: shaderManager_ = sm; } - // Only used by Qt UI? - bool DecodeTexture(u8 *output, const GPUgstate &state); - void ForgetLastTexture() override; void InvalidateLastTexture(TexCacheEntry *entry = nullptr) override; diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 9c0da49c11..1a0a7ee037 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -51,9 +51,6 @@ public: void DoState(PointerWrap &p) override; void ClearShaderCache() override; - bool DecodeTexture(u8 *dest, const GPUgstate &state) override { - return textureCacheDX9_->DecodeTexture(dest, state); - } bool FramebufferDirty() override; bool FramebufferReallyDirty() override; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 53e69baa56..a354f27994 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -780,12 +780,6 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re texture->UnlockRect(level); } -bool TextureCacheDX9::DecodeTexture(u8 *output, const GPUgstate &state) -{ - OutputDebugStringA("TextureCache::DecodeTexture : FixMe\r\n"); - return true; -} - bool TextureCacheDX9::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) { SetTexture(true); ApplyTexture(); diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 451cb922c5..a4c19572f4 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -49,9 +49,6 @@ public: shaderManager_ = sm; } - // Only used by Qt UI? - bool DecodeTexture(u8 *output, const GPUgstate &state); - void ForgetLastTexture() override; void InvalidateLastTexture(TexCacheEntry *entry = nullptr) override; diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 4378f166a7..f23c5ddf9d 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -55,9 +55,6 @@ public: void ClearShaderCache() override; void CleanupBeforeUI() override; - bool DecodeTexture(u8 *dest, const GPUgstate &state) override { - return textureCacheGL_->DecodeTexture(dest, state); - } bool FramebufferDirty() override; bool FramebufferReallyDirty() override; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 0430decbf1..7468c4a390 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -804,85 +804,6 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r } } -// Only used by Qt UI? -bool TextureCacheGLES::DecodeTexture(u8* output, const GPUgstate &state) { - GPUgstate oldState = gstate; - gstate = state; - - u32 texaddr = gstate.getTextureAddress(0); - - if (!Memory::IsValidAddress(texaddr)) { - return false; - } - - GLenum dstFmt = 0; - - GETextureFormat format = gstate.getTextureFormat(); - GEPaletteFormat clutformat = gstate.getClutPaletteFormat(); - u8 level = 0; - - int bufw = GetTextureBufw(level, texaddr, format); - int w = gstate.getTextureWidth(level); - int h = gstate.getTextureHeight(level); - - int pixelSize = dstFmt == GL_UNSIGNED_BYTE ? 4 : 2; - int decPitch = w * pixelSize; - - void *finalBuf = AllocateAlignedMemory(decPitch * h * pixelSize, 16); - DecodeTextureLevel((uint8_t *)finalBuf, decPitch, format, clutformat, texaddr, level, bufw, true, false, false); - - switch (dstFmt) { - case GL_UNSIGNED_SHORT_4_4_4_4: - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) { - u32 val = ((u16*)finalBuf)[y*w + x]; - u32 r = ((val>>12) & 0xF) * 17; - u32 g = ((val>> 8) & 0xF) * 17; - u32 b = ((val>> 4) & 0xF) * 17; - u32 a = ((val>> 0) & 0xF) * 17; - ((u32*)output)[y*w + x] = (a << 24) | (r << 16) | (g << 8) | b; - } - break; - - case GL_UNSIGNED_SHORT_5_5_5_1: - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) { - u32 val = ((u16*)finalBuf)[y*w + x]; - u32 r = Convert5To8((val>>11) & 0x1F); - u32 g = Convert5To8((val>> 6) & 0x1F); - u32 b = Convert5To8((val>> 1) & 0x1F); - u32 a = (val & 0x1) * 255; - ((u32*)output)[y*w + x] = (a << 24) | (r << 16) | (g << 8) | b; - } - break; - - case GL_UNSIGNED_SHORT_5_6_5: - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) { - u32 val = ((u16*)finalBuf)[y*w + x]; - u32 a = 0xFF; - u32 r = Convert5To8((val>>11) & 0x1F); - u32 g = Convert6To8((val>> 5) & 0x3F); - u32 b = Convert5To8((val ) & 0x1F); - ((u32*)output)[y*w + x] = (a << 24) | (r << 16) | (g << 8) | b; - } - break; - - default: - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) { - u32 val = ((u32*)finalBuf)[y*w + x]; - ((u32*)output)[y*w + x] = ((val & 0xFF000000)) | ((val & 0x00FF0000)>>16) | ((val & 0x0000FF00)) | ((val & 0x000000FF)<<16); - } - break; - } - - FreeAlignedMemory(finalBuf); - - gstate = oldState; - return true; -} - bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) { #ifndef USING_GLES2 GPUgstate saved; diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index eb81e44663..82756af4f6 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -63,9 +63,6 @@ public: } } - // Only used by Qt UI? - bool DecodeTexture(u8 *output, const GPUgstate &state); - void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight); bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 83653c3673..1890166ce8 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -227,9 +227,6 @@ public: const std::list& GetDisplayLists() override { return dlQueue; } - bool DecodeTexture(u8* dest, const GPUgstate &state) override { - return false; - } std::vector GetFramebufferList() override; void ClearShaderCache() override {} void CleanupBeforeUI() override {} diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index eeaa7c87a6..101f73e14b 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -241,7 +241,6 @@ public: virtual void DumpNextFrame() = 0; virtual void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) = 0; virtual const std::list& GetDisplayLists() = 0; - virtual bool DecodeTexture(u8* dest, const GPUgstate &state) = 0; virtual std::vector GetFramebufferList() = 0; virtual s64 GetListTicks(int listid) = 0; diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index fcbbf4145d..63813331fb 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -54,9 +54,6 @@ public: void DoState(PointerWrap &p) override; void ClearShaderCache() override; - bool DecodeTexture(u8 *dest, const GPUgstate &state) override { - return false; - } bool FramebufferDirty() override; bool FramebufferReallyDirty() override; diff --git a/Qt/Debugger/debugger_memorytex.cpp b/Qt/Debugger/debugger_memorytex.cpp index f077daaaf7..238c1371af 100644 --- a/Qt/Debugger/debugger_memorytex.cpp +++ b/Qt/Debugger/debugger_memorytex.cpp @@ -54,17 +54,7 @@ void Debugger_MemoryTex::on_readBtn_clicked() w = std::max(bufW,w); uchar* newData = new uchar[w*h*4]; - if(gpu->DecodeTexture(newData, state)) - { - QImage img = QImage(newData, w, h, w*4, QImage::Format_ARGB32); // EmuThread_GrabBackBuffer(); - - QPixmap pixmap = QPixmap::fromImage(img); - ui->textureImg->setPixmap(pixmap); - ui->textureImg->setMinimumWidth(pixmap.width()); - ui->textureImg->setMinimumHeight(pixmap.height()); - ui->textureImg->setMaximumWidth(pixmap.width()); - ui->textureImg->setMaximumHeight(pixmap.height()); - } + // TODO: Use GPU_GetCurrentTexture(). Warning: blocks. delete[] newData; } From 149ca17df6b1f0e0bd08cad236fd033ca04f4176 Mon Sep 17 00:00:00 2001 From: Kentucky Compass Date: Thu, 22 Feb 2018 03:04:12 -0800 Subject: [PATCH 169/291] iOS: fix hang on exit --- ios/ViewController.h | 4 +++ ios/ViewController.mm | 70 ++++++++++++++++++++++++++++++++----------- ios/main.mm | 9 +++++- 3 files changed, 65 insertions(+), 18 deletions(-) diff --git a/ios/ViewController.h b/ios/ViewController.h index eda8722ec2..4eedd89e7c 100644 --- a/ios/ViewController.h +++ b/ios/ViewController.h @@ -9,4 +9,8 @@ @interface ViewController : GLKViewController +- (void)shutdown; + @end + +extern __unsafe_unretained ViewController* sharedViewController; diff --git a/ios/ViewController.mm b/ios/ViewController.mm index f55496917c..9551f6a453 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -75,8 +75,9 @@ static double lastSelectPress = 0.0f; static double lastStartPress = 0.0f; static bool simulateAnalog = false; static bool threadEnabled = true; +static bool threadStopped = false; -__unsafe_unretained static ViewController* sharedViewController; +__unsafe_unretained ViewController* sharedViewController; static GraphicsContext *graphicsContext; @interface ViewController () @@ -114,6 +115,8 @@ static GraphicsContext *graphicsContext; iCadeToKeyMap[iCadeButtonG] = NKCODE_BUTTON_1; // Triangle iCadeToKeyMap[iCadeButtonH] = NKCODE_BUTTON_3; // Circle + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillTerminate:) name:UIApplicationWillTerminateNotification object:nil]; + #if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1 if ([GCController class]) // Checking the availability of a GameController framework { @@ -196,15 +199,20 @@ static GraphicsContext *graphicsContext; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ NativeInitGraphics(graphicsContext); + ILOG("Emulation thread starting\n"); while (threadEnabled) { NativeUpdate(); NativeRender(graphicsContext); time_update(); } + threadStopped = true; + + ILOG("Emulation thread shutting down\n"); NativeShutdownGraphics(); // Also ask the main thread to stop, so it doesn't hang waiting for a new frame. + ILOG("Emulation thread stopping\n"); graphicsContext->StopThread(); }); } @@ -214,33 +222,60 @@ static GraphicsContext *graphicsContext; [super didReceiveMemoryWarning]; } -- (void)dealloc +- (void)appWillTerminate:(NSNotification *)notification { - sharedViewController = nil; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; + [self shutdown]; +} + +- (void)shutdown +{ + if (sharedViewController == nil) { + return; } - self.context = nil; + + Audio_Shutdown(); + + if (threadEnabled) { + threadEnabled = false; + while (graphicsContext->ThreadFrame()) { + continue; + } + while (!threadStopped) {} + graphicsContext->ThreadEnd(); + } + + sharedViewController = nil; + + if (self.context) { + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + [[NSNotificationCenter defaultCenter] removeObserver:self]; #if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1 if ([GCController class]) { - [[NSNotificationCenter defaultCenter] removeObserver:self name:GCControllerDidConnectNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:GCControllerDidDisconnectNotification object:nil]; self.gameController = nil; } #endif - threadEnabled = false; - while (graphicsContext->ThreadFrame()) { - continue; - } - graphicsContext->ThreadEnd(); + graphicsContext->Shutdown(); - delete graphicsContext; - graphicsContext = NULL; + + if (graphicsContext) { + delete graphicsContext; + graphicsContext = NULL; + } + NativeShutdown(); } +- (void)dealloc +{ + [self shutdown]; +} + // For iOS before 6.0 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { @@ -255,7 +290,8 @@ static GraphicsContext *graphicsContext; - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { - graphicsContext->ThreadFrame(); + if (sharedViewController) + graphicsContext->ThreadFrame(); } - (void)touchX:(float)x y:(float)y code:(int)code pointerId:(int)pointerId diff --git a/ios/main.mm b/ios/main.mm index 8a5817982a..7e614bce38 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -9,6 +9,7 @@ #import "AppDelegate.h" #import "PPSSPPUIApplication.h" +#import "ViewController.h" #include "base/NativeApp.h" #include "profiler/profiler.h" @@ -24,6 +25,8 @@ @implementation UIApplication (SpringBoardAnimatedExit) -(void) animatedExit { + [sharedViewController shutdown]; + BOOL multitaskingSupported = NO; if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) { multitaskingSupported = [UIDevice currentDevice].multitaskingSupported; @@ -40,6 +43,8 @@ } -(void) exit { + [sharedViewController shutdown]; + if ([self respondsToSelector:@selector(terminateWithSuccess)]) { [self terminateWithSuccess]; } else { @@ -89,7 +94,9 @@ bool System_GetPropertyBool(SystemProperty prop) { void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { - [[UIApplication sharedApplication] animatedExit]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[UIApplication sharedApplication] animatedExit]; + }); } } From 506dfcb916355172b01ae6981947fa4b12830a63 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 22 Feb 2018 19:58:52 -0800 Subject: [PATCH 170/291] GLES: Fix texture scaling. Oops, and I had broken it again. --- GPU/GLES/TextureCacheGLES.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 7468c4a390..6aa92b3f5e 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -745,8 +745,6 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r GEPaletteFormat clutformat = gstate.getClutPaletteFormat(); u32 texaddr = gstate.getTextureAddress(level); int bufw = GetTextureBufw(level, texaddr, GETextureFormat(entry.format)); - int w = gstate.getTextureWidth(level); - int h = gstate.getTextureHeight(level); int pixelSize = dstFmt == GL_UNSIGNED_BYTE ? 4 : 2; int decPitch = w * pixelSize; @@ -754,9 +752,6 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r pixelData = (uint8_t *)AllocateAlignedMemory(decPitch * h * pixelSize, 16); DecodeTextureLevel(pixelData, decPitch, GETextureFormat(entry.format), clutformat, texaddr, level, bufw, true, false, false); - // Textures are always aligned to 16 bytes bufw, so this could safely be 4 always. - texByteAlign = dstFmt == GL_UNSIGNED_BYTE ? 4 : 2; - // We check before scaling since scaling shouldn't invent alpha from a full alpha texture. if ((entry.status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) { TexCacheEntry::TexStatus alphaStatus = CheckAlpha(pixelData, dstFmt, useUnpack ? bufw : w, w, h); @@ -772,6 +767,9 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r pixelData = rearrange; } + // Textures are always aligned to 16 bytes bufw, so this could safely be 4 always. + texByteAlign = dstFmt == GL_UNSIGNED_BYTE ? 4 : 2; + if (replacer_.Enabled()) { ReplacedTextureDecodeInfo replacedInfo; replacedInfo.cachekey = entry.CacheKey(); From d1a8514e7243360910a9aee9402f5d04dc616ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 24 Feb 2018 10:24:11 +0100 Subject: [PATCH 171/291] Vulkan: Dynamically grow descriptor pools as needed. Should help #10641 and similar issues. --- GPU/Vulkan/DrawEngineVulkan.cpp | 75 ++++++++++++++++++--------------- GPU/Vulkan/DrawEngineVulkan.h | 12 +++--- 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 6143778ddd..33b4fc7a9d 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -136,36 +136,10 @@ void DrawEngineVulkan::InitDeviceObjects() { VkResult res = vkCreateDescriptorSetLayout(device, &dsl, nullptr, &descriptorSetLayout_); assert(VK_SUCCESS == res); - VkDescriptorPoolSize dpTypes[3]; - dpTypes[0].descriptorCount = 8192; - dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - dpTypes[1].descriptorCount = 8192 + 4096; // Due to the tess stuff, we need a LOT of these. Most will be empty... - dpTypes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - dpTypes[2].descriptorCount = 2048; - dpTypes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - - VkDescriptorPoolCreateInfo dp = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; - dp.pNext = nullptr; - dp.flags = 0; // Don't want to mess around with individually freeing these. - // We zap the whole pool every few frames. - dp.maxSets = 2048; - dp.pPoolSizes = dpTypes; - dp.poolSizeCount = ARRAY_SIZE(dpTypes); - // We are going to use one-shot descriptors in the initial implementation. Might look into caching them // if creating and updating them turns out to be expensive. for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { - // If we run out of memory, try with less descriptors. - for (int tries = 0; tries < 3; ++tries) { - VkResult res = vkCreateDescriptorPool(vulkan_->GetDevice(), &dp, nullptr, &frame_[i].descPool); - if (res == VK_SUCCESS) { - break; - } - // Let's try to reduce the counts. - assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY); - dpTypes[0].descriptorCount /= 2; - dpTypes[1].descriptorCount /= 2; - } + // We now create descriptor pools on demand, so removed from here. frame_[i].pushUBO = new VulkanPushBuffer(vulkan_, 8 * 1024 * 1024); frame_[i].pushVertex = new VulkanPushBuffer(vulkan_, 2 * 1024 * 1024); frame_[i].pushIndex = new VulkanPushBuffer(vulkan_, 1 * 1024 * 1024); @@ -326,9 +300,9 @@ void DrawEngineVulkan::BeginFrame() { vertexCache_->BeginNoReset(); - // TODO: Need a better way to keep the number of descriptors under control. - if (--descDecimationCounter_ <= 0 || frame->descSets.size() > 1024) { - vkResetDescriptorPool(vulkan_->GetDevice(), frame->descPool, 0); + if (--descDecimationCounter_ <= 0) { + if (frame->descPool != VK_NULL_HANDLE) + vkResetDescriptorPool(vulkan_->GetDevice(), frame->descPool, 0); frame->descSets.Clear(); descDecimationCounter_ = DESCRIPTORSET_DECIMATION_INTERVAL; } @@ -461,14 +435,45 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView _dbg_assert_(G3D, light != VK_NULL_HANDLE); _dbg_assert_(G3D, bone != VK_NULL_HANDLE); - FrameData *frame = &frame_[vulkan_->GetCurFrame()]; + FrameData &frame = frame_[vulkan_->GetCurFrame()]; // See if we already have this descriptor set cached. if (!tess) { // Don't cache descriptors for HW tessellation. - VkDescriptorSet d = frame->descSets.Get(key); + VkDescriptorSet d = frame.descSets.Get(key); if (d != VK_NULL_HANDLE) return d; } + if (!frame.descPool || frame.descPoolSize < frame.descSets.size() + 1) { + // Reallocate this desc pool larger, and "wipe" the cache. We might lose a tiny bit of descriptor set reuse but + // only for this frame. + if (frame.descPool) { + DEBUG_LOG(G3D, "Reallocating desc pool from %d to %d", frame.descPoolSize, frame.descPoolSize * 2); + vulkan_->Delete().QueueDeleteDescriptorPool(frame.descPool); + frame.descSets.Clear(); + } + frame.descPoolSize *= 2; + + VkDescriptorPoolSize dpTypes[3]; + dpTypes[0].descriptorCount = frame.descPoolSize * 3; + dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + dpTypes[1].descriptorCount = frame.descPoolSize * 2; // Don't use these for tess anymore, need max two per set. + dpTypes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + dpTypes[2].descriptorCount = frame.descPoolSize; + dpTypes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + + VkDescriptorPoolCreateInfo dp = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; + dp.pNext = nullptr; + dp.flags = 0; // Don't want to mess around with individually freeing these. + // We zap the whole pool every few frames. + dp.maxSets = frame.descPoolSize; + dp.pPoolSizes = dpTypes; + dp.poolSizeCount = ARRAY_SIZE(dpTypes); + + VkResult res = vkCreateDescriptorPool(vulkan_->GetDevice(), &dp, nullptr, &frame.descPool); + assert(res == VK_SUCCESS); + } + + // Didn't find one in the frame descriptor set cache, let's make a new one. // We wipe the cache on every frame. @@ -476,11 +481,11 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView VkDescriptorSetAllocateInfo descAlloc = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; descAlloc.pNext = nullptr; descAlloc.pSetLayouts = &descriptorSetLayout_; - descAlloc.descriptorPool = frame->descPool; + descAlloc.descriptorPool = frame.descPool; descAlloc.descriptorSetCount = 1; VkResult result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc); // Even in release mode, this is bad. - _assert_msg_(G3D, result == VK_SUCCESS, "Ran out of descriptor space in pool. sz=%d res=%d", (int)frame->descSets.size(), (int)result); + _assert_msg_(G3D, result == VK_SUCCESS, "Ran out of descriptor space in pool. sz=%d res=%d", (int)frame.descSets.size(), (int)result); // We just don't write to the slots we don't care about. // We need 8 now that we support secondary texture bindings. @@ -573,7 +578,7 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView vkUpdateDescriptorSets(vulkan_->GetDevice(), n, writes, 0, nullptr); if (!tess) // Again, avoid caching when HW tessellation. - frame->descSets.Insert(key, desc); + frame.descSets.Insert(key, desc); return desc; } diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index c121bf297a..92d843ac57 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -229,12 +229,14 @@ private: // We alternate between these. struct FrameData { - FrameData() : descSets(1024) {} + FrameData() : descSets(512) {} - VkDescriptorPool descPool; - VulkanPushBuffer *pushUBO; - VulkanPushBuffer *pushVertex; - VulkanPushBuffer *pushIndex; + VkDescriptorPool descPool = VK_NULL_HANDLE; + int descPoolSize = 256; // We double this before we allocate so we initialize this to half the size we want. + + VulkanPushBuffer *pushUBO = nullptr; + VulkanPushBuffer *pushVertex = nullptr; + VulkanPushBuffer *pushIndex = nullptr; // We do rolling allocation and reset instead of caching across frames. That we might do later. DenseHashMap descSets; From 5d77c63216f413285a4e0acda37246fbea10b280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 24 Feb 2018 12:15:22 +0100 Subject: [PATCH 172/291] Vulkan: Need to count allocated descsets per frame separately from the map, since tess isn't even in-frame cached. --- GPU/Vulkan/DrawEngineVulkan.cpp | 5 ++++- GPU/Vulkan/DrawEngineVulkan.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 33b4fc7a9d..56a393f447 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -304,6 +304,7 @@ void DrawEngineVulkan::BeginFrame() { if (frame->descPool != VK_NULL_HANDLE) vkResetDescriptorPool(vulkan_->GetDevice(), frame->descPool, 0); frame->descSets.Clear(); + frame->descCount = 0; descDecimationCounter_ = DESCRIPTORSET_DECIMATION_INTERVAL; } @@ -443,13 +444,14 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView return d; } - if (!frame.descPool || frame.descPoolSize < frame.descSets.size() + 1) { + if (!frame.descPool || frame.descPoolSize < frame.descCount + 1) { // Reallocate this desc pool larger, and "wipe" the cache. We might lose a tiny bit of descriptor set reuse but // only for this frame. if (frame.descPool) { DEBUG_LOG(G3D, "Reallocating desc pool from %d to %d", frame.descPoolSize, frame.descPoolSize * 2); vulkan_->Delete().QueueDeleteDescriptorPool(frame.descPool); frame.descSets.Clear(); + frame.descCount = 0; } frame.descPoolSize *= 2; @@ -579,6 +581,7 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView if (!tess) // Again, avoid caching when HW tessellation. frame.descSets.Insert(key, desc); + frame.descCount++; return desc; } diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 92d843ac57..673cc4b4f4 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -232,6 +232,7 @@ private: FrameData() : descSets(512) {} VkDescriptorPool descPool = VK_NULL_HANDLE; + int descCount = 0; int descPoolSize = 256; // We double this before we allocate so we initialize this to half the size we want. VulkanPushBuffer *pushUBO = nullptr; From 5f8118b82b5123eb7a41b5974ec11dcf048f6910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 25 Feb 2018 10:27:59 +0100 Subject: [PATCH 173/291] Separate T3DCreate* into its own header to avoid including Windows.h etc in some cases. --- CMakeLists.txt | 1 + Common/CommonWindows.h | 3 ++- Core/Core.cpp | 1 + Qt/QtMain.h | 1 + UI/DevScreens.cpp | 1 + Windows/GPU/D3D11Context.cpp | 1 + Windows/GPU/D3D9Context.cpp | 1 + Windows/GPU/WindowsGLContext.cpp | 1 + Windows/GPU/WindowsVulkanContext.cpp | 1 + android/jni/AndroidEGLContext.cpp | 1 + android/jni/AndroidJavaGLContext.h | 1 + android/jni/AndroidVulkanContext.cpp | 1 + ext/native/gfx_es2/draw_buffer.h | 2 -- ext/native/native.vcxproj | 3 ++- ext/native/native.vcxproj.filters | 3 +++ ext/native/thin3d/thin3d.h | 31 +---------------------- ext/native/thin3d/thin3d_create.h | 38 ++++++++++++++++++++++++++++ headless/SDLHeadlessHost.cpp | 1 + ios/ViewController.mm | 1 + 19 files changed, 59 insertions(+), 34 deletions(-) create mode 100644 ext/native/thin3d/thin3d_create.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a687b91ede..5f7d160ece 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -980,6 +980,7 @@ add_library(native STATIC ext/native/profiler/profiler.h ext/native/thin3d/thin3d.cpp ext/native/thin3d/thin3d.h + ext/native/thin3d/thin3d_create.h ${THIN3D_PLATFORMS} ext/native/thread/executor.cpp ext/native/thread/executor.h diff --git a/Common/CommonWindows.h b/Common/CommonWindows.h index 255cd441db..bacd41cb5f 100644 --- a/Common/CommonWindows.h +++ b/Common/CommonWindows.h @@ -14,4 +14,5 @@ #undef min #undef max -#endif \ No newline at end of file +#undef DrawText +#endif diff --git a/Core/Core.cpp b/Core/Core.cpp index 450ea97595..a65c17e944 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -37,6 +37,7 @@ #include "Common/GraphicsContext.h" #ifdef _WIN32 +#include "Common/CommonWindows.h" #include "Windows/InputDevice.h" #endif diff --git a/Qt/QtMain.h b/Qt/QtMain.h index 191dd320ec..7f67794487 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -39,6 +39,7 @@ QTM_USE_NAMESPACE #include "Core/Core.h" #include "Core/Config.h" #include "Core/System.h" +#include "thin3d/thin3d_create.h" #include "thin3d/GLRenderManager.h" // Input diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index b6d25ae126..c499a90392 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -42,6 +42,7 @@ #include "UI/GameSettingsScreen.h" #ifdef _WIN32 +#include "Common/CommonWindows.h" // Want to avoid including the full header here as it includes d3dx.h int GetD3DXVersion(); #endif diff --git a/Windows/GPU/D3D11Context.cpp b/Windows/GPU/D3D11Context.cpp index b8ec01bd4b..e42ddd2eed 100644 --- a/Windows/GPU/D3D11Context.cpp +++ b/Windows/GPU/D3D11Context.cpp @@ -14,6 +14,7 @@ #include "Windows/GPU/D3D11Context.h" #include "Windows/W32Util/Misc.h" #include "thin3d/thin3d.h" +#include "thin3d/thin3d_create.h" #include "thin3d/d3d11_loader.h" #if PPSSPP_PLATFORM(UWP) diff --git a/Windows/GPU/D3D9Context.cpp b/Windows/GPU/D3D9Context.cpp index 19f772fb91..ad71c0a48d 100644 --- a/Windows/GPU/D3D9Context.cpp +++ b/Windows/GPU/D3D9Context.cpp @@ -14,6 +14,7 @@ #include "Windows/GPU/D3D9Context.h" #include "Windows/W32Util/Misc.h" #include "thin3d/thin3d.h" +#include "thin3d/thin3d_create.h" #include "thin3d/d3dx9_loader.h" void D3D9Context::SwapBuffers() { diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index b5dfc831d0..7bed8d1e69 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -21,6 +21,7 @@ #include "gfx/gl_common.h" #include "gfx/gl_debug_log.h" #include "gfx_es2/gpu_features.h" +#include "thin3d/thin3d_create.h" #include "thin3d/GLRenderManager.h" #include "GL/gl.h" #include "GL/wglew.h" diff --git a/Windows/GPU/WindowsVulkanContext.cpp b/Windows/GPU/WindowsVulkanContext.cpp index 67e6f51954..0e71ace543 100644 --- a/Windows/GPU/WindowsVulkanContext.cpp +++ b/Windows/GPU/WindowsVulkanContext.cpp @@ -58,6 +58,7 @@ #include "base/stringutil.h" #include "thin3d/thin3d.h" +#include "thin3d/thin3d_create.h" #include "thin3d/VulkanRenderManager.h" #include "util/text/parsers.h" #include "Windows/GPU/WindowsVulkanContext.h" diff --git a/android/jni/AndroidEGLContext.cpp b/android/jni/AndroidEGLContext.cpp index 68438cce21..1a40994cf7 100644 --- a/android/jni/AndroidEGLContext.cpp +++ b/android/jni/AndroidEGLContext.cpp @@ -2,6 +2,7 @@ #include "base/logging.h" #include "base/NativeApp.h" #include "gfx_es2/gpu_features.h" +#include "thin3d/thin3d_create.h" #include "AndroidEGLContext.h" #include "GL/GLInterface/EGLAndroid.h" diff --git a/android/jni/AndroidJavaGLContext.h b/android/jni/AndroidJavaGLContext.h index 44f062bd78..7b47f58f3c 100644 --- a/android/jni/AndroidJavaGLContext.h +++ b/android/jni/AndroidJavaGLContext.h @@ -6,6 +6,7 @@ #include "AndroidGraphicsContext.h" #include "thin3d/GLRenderManager.h" +#include "thin3d/thin3d_create.h" // Doesn't do much. Just to fit in. class AndroidJavaEGLGraphicsContext : public AndroidGraphicsContext { diff --git a/android/jni/AndroidVulkanContext.cpp b/android/jni/AndroidVulkanContext.cpp index b067d7f533..04481b3377 100644 --- a/android/jni/AndroidVulkanContext.cpp +++ b/android/jni/AndroidVulkanContext.cpp @@ -6,6 +6,7 @@ #include "Common/Vulkan/VulkanLoader.h" #include "Common/Vulkan/VulkanContext.h" #include "thin3d/VulkanRenderManager.h" +#include "thin3d/thin3d_create.h" #include "util/text/parsers.h" #include "Core/Config.h" #include "Core/System.h" diff --git a/ext/native/gfx_es2/draw_buffer.h b/ext/native/gfx_es2/draw_buffer.h index 2734d065b2..e797152554 100644 --- a/ext/native/gfx_es2/draw_buffer.h +++ b/ext/native/gfx_es2/draw_buffer.h @@ -11,8 +11,6 @@ #include "math/lin/matrix4x4.h" #include "thin3d/thin3d.h" -#undef DrawText - struct Atlas; enum { diff --git a/ext/native/native.vcxproj b/ext/native/native.vcxproj index ebb1517ea2..8d43e4329d 100644 --- a/ext/native/native.vcxproj +++ b/ext/native/native.vcxproj @@ -243,6 +243,7 @@ + @@ -766,4 +767,4 @@ - + \ No newline at end of file diff --git a/ext/native/native.vcxproj.filters b/ext/native/native.vcxproj.filters index e0507e183a..aecf223674 100644 --- a/ext/native/native.vcxproj.filters +++ b/ext/native/native.vcxproj.filters @@ -338,6 +338,9 @@ thin3d + + thin3d + diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index cbd46e2d4a..d4f4134e65 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -6,7 +6,7 @@ #pragma once -#include +#include #include #include #include @@ -16,26 +16,6 @@ class Matrix4x4; -#ifdef _WIN32 -#ifndef NOMINMAX -#define NOMINMAX -#endif -#define WIN32_LEAN_AND_MEAN -#include -#include -struct IDirect3DDevice9; -struct IDirect3D9; -struct IDirect3DDevice9Ex; -struct IDirect3D9Ex; -struct ID3D11Device; -struct ID3D11DeviceContext; -struct ID3D11Device1; -struct ID3D11DeviceContext1; - -#endif - -class VulkanContext; - namespace Draw { // Useful in UBOs @@ -664,17 +644,8 @@ protected: int targetHeight_; }; -DrawContext *T3DCreateGLContext(); - extern const UniformBufferDesc UBPresetDesc; -#ifdef _WIN32 -DrawContext *T3DCreateDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx); -DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd); -#endif - -DrawContext *T3DCreateVulkanContext(VulkanContext *context, bool split); - // UBs for the preset shaders struct VsTexColUB { diff --git a/ext/native/thin3d/thin3d_create.h b/ext/native/thin3d/thin3d_create.h new file mode 100644 index 0000000000..3d4ea0f1a4 --- /dev/null +++ b/ext/native/thin3d/thin3d_create.h @@ -0,0 +1,38 @@ +#pragma once + +#include "thin3d/thin3d.h" + +// Separated this stuff into its own file so we don't get Windows.h included if all we want is the thin3d declarations. + +#ifdef _WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#define WIN32_LEAN_AND_MEAN +#include +#include +struct IDirect3DDevice9; +struct IDirect3D9; +struct IDirect3DDevice9Ex; +struct IDirect3D9Ex; +struct ID3D11Device; +struct ID3D11DeviceContext; +struct ID3D11Device1; +struct ID3D11DeviceContext1; + +#endif + +class VulkanContext; + +namespace Draw { + +DrawContext *T3DCreateGLContext(); + +#ifdef _WIN32 +DrawContext *T3DCreateDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx); +DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd); +#endif + +DrawContext *T3DCreateVulkanContext(VulkanContext *context, bool split); + +} // namespace Draw diff --git a/headless/SDLHeadlessHost.cpp b/headless/SDLHeadlessHost.cpp index 17026f7fca..ed60e409d9 100644 --- a/headless/SDLHeadlessHost.cpp +++ b/headless/SDLHeadlessHost.cpp @@ -36,6 +36,7 @@ #include "gfx_es2/gpu_features.h" #include "file/vfs.h" #include "file/zip_read.h" +#include "thin3d/thin3d_create.h" const bool WINDOW_VISIBLE = false; const int WINDOW_WIDTH = 480; diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 9551f6a453..4f7dcaad16 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -16,6 +16,7 @@ #include "net/resolve.h" #include "ui/screen.h" #include "thin3d/thin3d.h" +#include "thin3d/thin3d_create.h" #include "thin3d/GLRenderManager.h" #include "input/keycodes.h" #include "gfx_es2/gpu_features.h" From 4b4a2a4096cc342723b46f37b3ae5eae96fea7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 25 Feb 2018 11:25:16 +0100 Subject: [PATCH 174/291] Buildfixes --- SDL/SDLGLGraphicsContext.cpp | 1 + SDL/SDLVulkanGraphicsContext.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp index f8f69fd02c..3693c77c5a 100644 --- a/SDL/SDLGLGraphicsContext.cpp +++ b/SDL/SDLGLGraphicsContext.cpp @@ -4,6 +4,7 @@ #include "base/NativeApp.h" #include "base/display.h" #include "gfx_es2/gpu_features.h" +#include "thin3d/thin3d_create.h" class GLRenderManager; diff --git a/SDL/SDLVulkanGraphicsContext.cpp b/SDL/SDLVulkanGraphicsContext.cpp index 2c868b2a37..898d2c3a2a 100644 --- a/SDL/SDLVulkanGraphicsContext.cpp +++ b/SDL/SDLVulkanGraphicsContext.cpp @@ -2,6 +2,7 @@ #include "base/NativeApp.h" #include "base/display.h" #include "thin3d/thin3d.h" +#include "thin3d/thin3d_create.h" #include "util/text/parsers.h" #include "Core/System.h" From 8e0e5f9aa6e248f9bbb477c3e0cb0475041052c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 24 Feb 2018 13:33:06 +0100 Subject: [PATCH 175/291] Extract RecreateDescriptorPool() --- GPU/Vulkan/DrawEngineVulkan.cpp | 60 ++++++++++++++++++--------------- GPU/Vulkan/DrawEngineVulkan.h | 1 + 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 56a393f447..955ae60480 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -424,6 +424,37 @@ void DrawEngineVulkan::SetLineWidth(float lineWidth) { pipelineManager_->SetLineWidth(lineWidth); } +VkResult DrawEngineVulkan::RecreateDescriptorPool(FrameData &frame, int newSize) { + // Reallocate this desc pool larger, and "wipe" the cache. We might lose a tiny bit of descriptor set reuse but + // only for this frame. + if (frame.descPool) { + DEBUG_LOG(G3D, "Reallocating desc pool from %d to %d", frame.descPoolSize, newSize); + vulkan_->Delete().QueueDeleteDescriptorPool(frame.descPool); + frame.descSets.Clear(); + frame.descCount = 0; + } + frame.descPoolSize = newSize; + + VkDescriptorPoolSize dpTypes[3]; + dpTypes[0].descriptorCount = frame.descPoolSize * 3; + dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + dpTypes[1].descriptorCount = frame.descPoolSize * 2; // Don't use these for tess anymore, need max two per set. + dpTypes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + dpTypes[2].descriptorCount = frame.descPoolSize; + dpTypes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + + VkDescriptorPoolCreateInfo dp = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; + dp.pNext = nullptr; + dp.flags = 0; // Don't want to mess around with individually freeing these. + // We zap the whole pool every few frames. + dp.maxSets = frame.descPoolSize; + dp.pPoolSizes = dpTypes; + dp.poolSizeCount = ARRAY_SIZE(dpTypes); + + VkResult res = vkCreateDescriptorPool(vulkan_->GetDevice(), &dp, nullptr, &frame.descPool); + return res; +} + VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView, VkSampler sampler, VkBuffer base, VkBuffer light, VkBuffer bone, bool tess) { DescriptorSetKey key; key.imageView_ = imageView; @@ -445,37 +476,10 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView } if (!frame.descPool || frame.descPoolSize < frame.descCount + 1) { - // Reallocate this desc pool larger, and "wipe" the cache. We might lose a tiny bit of descriptor set reuse but - // only for this frame. - if (frame.descPool) { - DEBUG_LOG(G3D, "Reallocating desc pool from %d to %d", frame.descPoolSize, frame.descPoolSize * 2); - vulkan_->Delete().QueueDeleteDescriptorPool(frame.descPool); - frame.descSets.Clear(); - frame.descCount = 0; - } - frame.descPoolSize *= 2; - - VkDescriptorPoolSize dpTypes[3]; - dpTypes[0].descriptorCount = frame.descPoolSize * 3; - dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - dpTypes[1].descriptorCount = frame.descPoolSize * 2; // Don't use these for tess anymore, need max two per set. - dpTypes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - dpTypes[2].descriptorCount = frame.descPoolSize; - dpTypes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - - VkDescriptorPoolCreateInfo dp = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; - dp.pNext = nullptr; - dp.flags = 0; // Don't want to mess around with individually freeing these. - // We zap the whole pool every few frames. - dp.maxSets = frame.descPoolSize; - dp.pPoolSizes = dpTypes; - dp.poolSizeCount = ARRAY_SIZE(dpTypes); - - VkResult res = vkCreateDescriptorPool(vulkan_->GetDevice(), &dp, nullptr, &frame.descPool); + VkResult res = RecreateDescriptorPool(frame, frame.descPoolSize * 2); assert(res == VK_SUCCESS); } - // Didn't find one in the frame descriptor set cache, let's make a new one. // We wipe the cache on every frame. diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 673cc4b4f4..15890cefde 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -195,6 +195,7 @@ private: void DestroyDeviceObjects(); void DecodeVertsToPushBuffer(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf); + VkResult RecreateDescriptorPool(FrameData &frame, int newSize); void DoFlush(); void UpdateUBOs(FrameData *frame); From b7b5c5e2111d2703cbb51a5280f666880d15d70f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 24 Feb 2018 13:35:15 +0100 Subject: [PATCH 176/291] Follow the spec rules about errors when allocating from descriptor pools See https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkAllocateDescriptorSets.html --- GPU/Vulkan/DrawEngineVulkan.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 955ae60480..12846fe536 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -490,6 +490,18 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView descAlloc.descriptorPool = frame.descPool; descAlloc.descriptorSetCount = 1; VkResult result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc); + + if (result == VK_ERROR_FRAGMENTED_POOL || result < 0) { + // There seems to have been a spec revision. Here we should apparently recreate the descriptor pool, + // so let's do that. See https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkAllocateDescriptorSets.html + // Fragmentation shouldn't really happen though since we wipe the pool every frame.. + VkResult res = RecreateDescriptorPool(frame, frame.descPoolSize); + _assert_msg_(G3D, res == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to recreate a descriptor pool. sz=%d res=%d", (int)frame.descSets.size(), (int)res); + descAlloc.descriptorPool = frame.descPool; // Need to update this pointer since we have allocated a new one. + result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc); + _assert_msg_(G3D, result == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to allocate after recreating a descriptor pool. res=%d", (int)result); + } + // Even in release mode, this is bad. _assert_msg_(G3D, result == VK_SUCCESS, "Ran out of descriptor space in pool. sz=%d res=%d", (int)frame.descSets.size(), (int)result); From eb014e8c6b52666f159000bc216ef612cc869cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 24 Feb 2018 16:55:32 +0100 Subject: [PATCH 177/291] Try to be more consistent when initializing vulkan structs. --- Common/Vulkan/VulkanContext.cpp | 4 ++-- Common/Vulkan/VulkanImage.cpp | 14 +++++++------- Common/Vulkan/VulkanMemory.cpp | 8 ++++---- GPU/Vulkan/DrawEngineVulkan.cpp | 19 ++++++------------- GPU/Vulkan/PipelineManagerVulkan.cpp | 18 +++++++++--------- 5 files changed, 28 insertions(+), 35 deletions(-) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index 8854970e9d..12993524ef 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -547,7 +547,7 @@ VkResult VulkanContext::CreateDevice() { return VK_ERROR_INITIALIZATION_FAILED; } - VkDeviceQueueCreateInfo queue_info = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; + VkDeviceQueueCreateInfo queue_info{ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; float queue_priorities[1] = { 1.0f }; queue_info.queueCount = 1; queue_info.pQueuePriorities = queue_priorities; @@ -563,7 +563,7 @@ VkResult VulkanContext::CreateDevice() { deviceExtensionsLookup_.DEDICATED_ALLOCATION = EnableDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME); - VkDeviceCreateInfo device_info { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; + VkDeviceCreateInfo device_info{ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; device_info.queueCreateInfoCount = 1; device_info.pQueueCreateInfos = &queue_info; device_info.enabledLayerCount = (uint32_t)device_layer_names_.size(); diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index 143ad16332..170a9a3873 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -90,7 +90,7 @@ void VulkanTexture::Unlock(VkCommandBuffer cmd) { Wipe(); { // Shrink the diff by not unindenting. If you make major changes, remove this. - VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + VkImageCreateInfo image_create_info{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; image_create_info.imageType = VK_IMAGE_TYPE_2D; image_create_info.format = format_; image_create_info.extent.width = tex_width; @@ -113,7 +113,7 @@ void VulkanTexture::Unlock(VkCommandBuffer cmd) { vkGetImageMemoryRequirements(vulkan_->GetDevice(), image, &mem_reqs); - VkMemoryAllocateInfo mem_alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + VkMemoryAllocateInfo mem_alloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; mem_alloc.memoryTypeIndex = 0; mem_alloc.allocationSize = mem_reqs.size; @@ -183,7 +183,7 @@ void VulkanTexture::Unlock(VkCommandBuffer cmd) { vulkan_->Delete().QueueDeleteDeviceMemory(mappableMemory); } - VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + VkImageViewCreateInfo view_info{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; view_info.image = image; view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; view_info.format = format_; @@ -238,7 +238,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, VkImageAspectFlags aspect = IsDepthStencilFormat(format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; - VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + VkImageCreateInfo image_create_info{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; image_create_info.imageType = VK_IMAGE_TYPE_2D; image_create_info.format = format_; image_create_info.extent.width = tex_width; @@ -270,7 +270,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, return false; } } else { - VkMemoryAllocateInfo mem_alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + VkMemoryAllocateInfo mem_alloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; mem_alloc.memoryTypeIndex = 0; mem_alloc.allocationSize = mem_reqs.size; @@ -312,7 +312,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, } // Create the view while we're at it. - VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + VkImageViewCreateInfo view_info{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; view_info.image = image; view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; view_info.format = format_; @@ -339,7 +339,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, } void VulkanTexture::UploadMip(VkCommandBuffer cmd, int mip, int mipWidth, int mipHeight, VkBuffer buffer, uint32_t offset, size_t rowLength) { - VkBufferImageCopy copy_region = {}; + VkBufferImageCopy copy_region{}; copy_region.bufferOffset = offset; copy_region.bufferRowLength = (uint32_t)rowLength; copy_region.bufferImageHeight = 0; // 2D diff --git a/Common/Vulkan/VulkanMemory.cpp b/Common/Vulkan/VulkanMemory.cpp index 4460a57492..1e7929202e 100644 --- a/Common/Vulkan/VulkanMemory.cpp +++ b/Common/Vulkan/VulkanMemory.cpp @@ -36,7 +36,7 @@ VulkanPushBuffer::~VulkanPushBuffer() { bool VulkanPushBuffer::AddBuffer() { BufInfo info; - VkBufferCreateInfo b = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + VkBufferCreateInfo b{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; b.size = size_; b.flags = 0; b.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; @@ -56,7 +56,7 @@ bool VulkanPushBuffer::AddBuffer() { // TODO: We really should use memoryTypeIndex here.. // Okay, that's the buffer. Now let's allocate some memory for it. - VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + VkMemoryAllocateInfo alloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; // TODO: Should check here that memoryTypeIndex_ matches reqs.memoryTypeBits. alloc.memoryTypeIndex = memoryTypeIndex_; alloc.allocationSize = reqs.size; @@ -145,7 +145,7 @@ void VulkanPushBuffer::Unmap() { assert(writePtr_); /* // Should not need this since we use coherent memory. - VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE }; + VkMappedMemoryRange range{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE }; range.offset = 0; range.size = offset_; range.memory = buffers_[buf_].deviceMemory; @@ -380,7 +380,7 @@ bool VulkanDeviceAllocator::AllocateSlab(VkDeviceSize minBytes) { minSlabSize_ <<= 1; } - VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + VkMemoryAllocateInfo alloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; alloc.allocationSize = minSlabSize_; alloc.memoryTypeIndex = memoryTypeIndex_; diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 12846fe536..122b50ddaa 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -95,42 +95,36 @@ DrawEngineVulkan::DrawEngineVulkan(VulkanContext *vulkan, Draw::DrawContext *dra void DrawEngineVulkan::InitDeviceObjects() { // All resources we need for PSP drawing. Usually only bindings 0 and 2-4 are populated. - VkDescriptorSetLayoutBinding bindings[6]; + VkDescriptorSetLayoutBinding bindings[6]{}; bindings[0].descriptorCount = 1; - bindings[0].pImmutableSamplers = nullptr; bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; bindings[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; bindings[0].binding = DRAW_BINDING_TEXTURE; bindings[1].descriptorCount = 1; - bindings[1].pImmutableSamplers = nullptr; bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; bindings[1].binding = DRAW_BINDING_2ND_TEXTURE; bindings[2].descriptorCount = 1; - bindings[2].pImmutableSamplers = nullptr; bindings[2].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; bindings[2].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; bindings[2].binding = DRAW_BINDING_DYNUBO_BASE; bindings[3].descriptorCount = 1; - bindings[3].pImmutableSamplers = nullptr; bindings[3].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; bindings[3].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; bindings[3].binding = DRAW_BINDING_DYNUBO_LIGHT; bindings[4].descriptorCount = 1; - bindings[4].pImmutableSamplers = nullptr; bindings[4].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; bindings[4].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; bindings[4].binding = DRAW_BINDING_DYNUBO_BONE; // Used only for hardware tessellation. bindings[5].descriptorCount = 1; - bindings[5].pImmutableSamplers = nullptr; bindings[5].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; bindings[5].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; bindings[5].binding = DRAW_BINDING_TESS_STORAGE_BUF; VkDevice device = vulkan_->GetDevice(); - VkDescriptorSetLayoutCreateInfo dsl = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; + VkDescriptorSetLayoutCreateInfo dsl{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; dsl.bindingCount = ARRAY_SIZE(bindings); dsl.pBindings = bindings; VkResult res = vkCreateDescriptorSetLayout(device, &dsl, nullptr, &descriptorSetLayout_); @@ -145,7 +139,7 @@ void DrawEngineVulkan::InitDeviceObjects() { frame_[i].pushIndex = new VulkanPushBuffer(vulkan_, 1 * 1024 * 1024); } - VkPipelineLayoutCreateInfo pl = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; + VkPipelineLayoutCreateInfo pl{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; pl.pPushConstantRanges = nullptr; pl.pushConstantRangeCount = 0; pl.setLayoutCount = 1; @@ -154,7 +148,7 @@ void DrawEngineVulkan::InitDeviceObjects() { res = vkCreatePipelineLayout(device, &pl, nullptr, &pipelineLayout_); assert(VK_SUCCESS == res); - VkSamplerCreateInfo samp = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; + VkSamplerCreateInfo samp{ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; samp.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samp.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samp.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; @@ -443,8 +437,7 @@ VkResult DrawEngineVulkan::RecreateDescriptorPool(FrameData &frame, int newSize) dpTypes[2].descriptorCount = frame.descPoolSize; dpTypes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - VkDescriptorPoolCreateInfo dp = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; - dp.pNext = nullptr; + VkDescriptorPoolCreateInfo dp{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; dp.flags = 0; // Don't want to mess around with individually freeing these. // We zap the whole pool every few frames. dp.maxSets = frame.descPoolSize; @@ -484,7 +477,7 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView // We wipe the cache on every frame. VkDescriptorSet desc; - VkDescriptorSetAllocateInfo descAlloc = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; + VkDescriptorSetAllocateInfo descAlloc{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; descAlloc.pNext = nullptr; descAlloc.pSetLayouts = &descriptorSetLayout_; descAlloc.descriptorPool = frame.descPool; diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 4dcd4b6235..eabd8a1827 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -133,7 +133,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip } blend0.colorWriteMask = key.colorWriteMask; - VkPipelineColorBlendStateCreateInfo cbs = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO }; + VkPipelineColorBlendStateCreateInfo cbs{ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO }; cbs.flags = 0; cbs.pAttachments = &blend0; cbs.attachmentCount = 1; @@ -143,7 +143,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip else cbs.logicOp = VK_LOGIC_OP_COPY; - VkPipelineDepthStencilStateCreateInfo dss = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO }; + VkPipelineDepthStencilStateCreateInfo dss{ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO }; dss.depthBoundsTestEnable = false; dss.stencilTestEnable = key.stencilTestEnable; if (key.stencilTestEnable) { @@ -175,12 +175,12 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip dynamicStates[numDyn++] = VK_DYNAMIC_STATE_STENCIL_REFERENCE; } - VkPipelineDynamicStateCreateInfo ds = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; + VkPipelineDynamicStateCreateInfo ds{ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; ds.flags = 0; ds.pDynamicStates = dynamicStates; ds.dynamicStateCount = numDyn; - VkPipelineRasterizationStateCreateInfo rs = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO }; + VkPipelineRasterizationStateCreateInfo rs{ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO }; rs.flags = 0; rs.depthBiasEnable = false; rs.cullMode = key.cullMode; @@ -190,7 +190,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip rs.polygonMode = VK_POLYGON_MODE_FILL; rs.depthClampEnable = key.depthClampEnable; - VkPipelineMultisampleStateCreateInfo ms = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO }; + VkPipelineMultisampleStateCreateInfo ms{ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO }; ms.pSampleMask = nullptr; ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; @@ -215,7 +215,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip return nullptr; } - VkPipelineInputAssemblyStateCreateInfo inputAssembly = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; + VkPipelineInputAssemblyStateCreateInfo inputAssembly{ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; inputAssembly.flags = 0; inputAssembly.topology = (VkPrimitiveTopology)key.topology; inputAssembly.primitiveRestartEnable = false; @@ -238,21 +238,21 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip ibd.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; ibd.stride = vertexStride; - VkPipelineVertexInputStateCreateInfo vis = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; + VkPipelineVertexInputStateCreateInfo vis{ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; vis.flags = 0; vis.vertexBindingDescriptionCount = 1; vis.pVertexBindingDescriptions = &ibd; vis.vertexAttributeDescriptionCount = attributeCount; vis.pVertexAttributeDescriptions = attrs; - VkPipelineViewportStateCreateInfo views = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO }; + VkPipelineViewportStateCreateInfo views{ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO }; views.flags = 0; views.viewportCount = 1; views.scissorCount = 1; views.pViewports = nullptr; // dynamic views.pScissors = nullptr; // dynamic - VkGraphicsPipelineCreateInfo pipe = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO }; + VkGraphicsPipelineCreateInfo pipe{ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO }; pipe.flags = 0; pipe.stageCount = 2; pipe.pStages = ss; From e1852321a085565590b42af4f4563bdca539569e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 25 Feb 2018 10:13:01 +0100 Subject: [PATCH 178/291] Vulkan: Remove the old method of uploading images. --- Common/Vulkan/VulkanImage.cpp | 205 +--------------------------- Common/Vulkan/VulkanImage.h | 17 +-- UI/NativeApp.cpp | 18 --- UI/TextureUtil.h | 1 - ext/native/thin3d/thin3d_vulkan.cpp | 61 +++++---- ext/native/ui/ui_context.cpp | 16 ++- ext/native/ui/ui_context.h | 5 +- ext/native/ui/ui_screen.cpp | 1 + 8 files changed, 52 insertions(+), 272 deletions(-) diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index 170a9a3873..fa5969ad3e 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -2,204 +2,6 @@ #include "Common/Vulkan/VulkanMemory.h" #include "Common/Log.h" -VkResult VulkanTexture::Create(int w, int h, VkFormat format) { - tex_width = w; - tex_height = h; - format_ = format; - - VkFormatProperties formatProps; - vkGetPhysicalDeviceFormatProperties(vulkan_->GetPhysicalDevice(), format, &formatProps); - return VK_SUCCESS; -} - -void VulkanTexture::CreateMappableImage() { - // If we already have a mappableImage, forget it. - if (mappableImage) { - vulkan_->Delete().QueueDeleteImage(mappableImage); - } - if (mappableMemory) { - vulkan_->Delete().QueueDeleteDeviceMemory(mappableMemory); - } - - VkImageCreateInfo image_create_info{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = format_; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_LINEAR; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - image_create_info.queueFamilyIndexCount = 0; - image_create_info.pQueueFamilyIndices = NULL; - image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_create_info.flags = 0; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - - VkMemoryAllocateInfo mem_alloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; - mem_alloc.allocationSize = 0; - mem_alloc.memoryTypeIndex = 0; - - // Create a mappable image. It will be the texture if linear images are ok to be textures - // or it will be the staging image if they are not. - VkResult res = vkCreateImage(vulkan_->GetDevice(), &image_create_info, NULL, &mappableImage); - assert(res == VK_SUCCESS); - - vkGetImageMemoryRequirements(vulkan_->GetDevice(), mappableImage, &mem_reqs); - assert(res == VK_SUCCESS); - - mem_alloc.allocationSize = mem_reqs.size; - - // Find the memory type that is host mappable. - bool pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &mem_alloc.memoryTypeIndex); - assert(pass); - - res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mappableMemory); - assert(res == VK_SUCCESS); - - res = vkBindImageMemory(vulkan_->GetDevice(), mappableImage, mappableMemory, 0); - assert(res == VK_SUCCESS); -} - -uint8_t *VulkanTexture::Lock(int level, int *rowPitch) { - CreateMappableImage(); - - VkImageSubresource subres = {}; - subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subres.mipLevel = 0; - subres.arrayLayer = 0; - - VkSubresourceLayout layout; - void *data; - - // Get the subresource layout so we know what the row pitch is - vkGetImageSubresourceLayout(vulkan_->GetDevice(), mappableImage, &subres, &layout); - VkResult res = vkMapMemory(vulkan_->GetDevice(), mappableMemory, layout.offset, layout.size, 0, &data); - assert(res == VK_SUCCESS); - - *rowPitch = (int)layout.rowPitch; - return (uint8_t *)data; -} - -void VulkanTexture::Unlock(VkCommandBuffer cmd) { - vkUnmapMemory(vulkan_->GetDevice(), mappableMemory); - - // if we already have an image, queue it for destruction and forget it. - Wipe(); - - { // Shrink the diff by not unindenting. If you make major changes, remove this. - VkImageCreateInfo image_create_info{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = format_; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.queueFamilyIndexCount = 0; - image_create_info.pQueueFamilyIndices = NULL; - image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_create_info.flags = 0; - // The mappable image cannot be our texture, so create an optimally tiled image and blit to it - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkResult res = vkCreateImage(vulkan_->GetDevice(), &image_create_info, NULL, &image); - assert(res == VK_SUCCESS); - - vkGetImageMemoryRequirements(vulkan_->GetDevice(), image, &mem_reqs); - - VkMemoryAllocateInfo mem_alloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; - mem_alloc.memoryTypeIndex = 0; - mem_alloc.allocationSize = mem_reqs.size; - - if (allocator_) { - offset_ = allocator_->Allocate(mem_reqs, &mem); - } else { - offset_ = 0; - // Find memory type - don't specify any mapping requirements - bool pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mem_alloc.memoryTypeIndex); - assert(pass); - res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mem); - assert(res == VK_SUCCESS); - } - - res = vkBindImageMemory(vulkan_->GetDevice(), image, mem, offset_); - assert(res == VK_SUCCESS); - - // Since we're going to blit from the mappable image, set its layout to SOURCE_OPTIMAL - TransitionImageLayout2(cmd, mappableImage, 0, 1, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT); - - TransitionImageLayout2(cmd, image, 0, 1, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, VK_ACCESS_TRANSFER_WRITE_BIT); - - VkImageCopy copy_region; - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.srcSubresource.mipLevel = 0; - copy_region.srcSubresource.baseArrayLayer = 0; - copy_region.srcSubresource.layerCount = 1; - copy_region.srcOffset.x = 0; - copy_region.srcOffset.y = 0; - copy_region.srcOffset.z = 0; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.dstSubresource.mipLevel = 0; - copy_region.dstSubresource.baseArrayLayer = 0; - copy_region.dstSubresource.layerCount = 1; - copy_region.dstOffset.x = 0; - copy_region.dstOffset.y = 0; - copy_region.dstOffset.z = 0; - copy_region.extent.width = tex_width; - copy_region.extent.height = tex_height; - copy_region.extent.depth = 1; - - // Put the copy command into the command buffer - vkCmdCopyImage(cmd, - mappableImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, ©_region); - - assert(res == VK_SUCCESS); - - // Set the layout for the texture image from DESTINATION_OPTIMAL to SHADER_READ_ONLY - TransitionImageLayout2(cmd, image, 0, 1, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); - - // Then drop the temporary mappable image - although should not be necessary... - vulkan_->Delete().QueueDeleteImage(mappableImage); - vulkan_->Delete().QueueDeleteDeviceMemory(mappableMemory); - } - - VkImageViewCreateInfo view_info{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; - view_info.image = image; - view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - view_info.format = format_; - view_info.components.r = VK_COMPONENT_SWIZZLE_R; - view_info.components.g = VK_COMPONENT_SWIZZLE_G; - view_info.components.b = VK_COMPONENT_SWIZZLE_B; - view_info.components.a = VK_COMPONENT_SWIZZLE_A; - view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - view_info.subresourceRange.baseMipLevel = 0; - view_info.subresourceRange.levelCount = 1; - view_info.subresourceRange.baseArrayLayer = 0; - view_info.subresourceRange.layerCount = 1; - VkResult res = vkCreateImageView(vulkan_->GetDevice(), &view_info, NULL, &view); - assert(res == VK_SUCCESS); -} - void VulkanTexture::Wipe() { if (image) { vulkan_->Delete().QueueDeleteImage(image); @@ -262,6 +64,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, return false; } + VkMemoryRequirements mem_reqs{}; vkGetImageMemoryRequirements(vulkan_->GetDevice(), image, &mem_reqs); if (allocator_) { @@ -399,15 +202,9 @@ void VulkanTexture::Destroy() { vulkan_->Delete().QueueDeleteImageView(view); } if (image != VK_NULL_HANDLE) { - if (mappableImage == image) { - mappableImage = VK_NULL_HANDLE; - } vulkan_->Delete().QueueDeleteImage(image); } if (mem != VK_NULL_HANDLE && !allocator_) { - if (mappableMemory == mem) { - mappableMemory = VK_NULL_HANDLE; - } vulkan_->Delete().QueueDeleteDeviceMemory(mem); } else if (mem != VK_NULL_HANDLE) { allocator_->Free(mem, offset_); diff --git a/Common/Vulkan/VulkanImage.h b/Common/Vulkan/VulkanImage.h index 2b8486c975..df2a45edd1 100644 --- a/Common/Vulkan/VulkanImage.h +++ b/Common/Vulkan/VulkanImage.h @@ -11,23 +11,12 @@ public: VulkanTexture(VulkanContext *vulkan, VulkanDeviceAllocator *allocator) : vulkan_(vulkan), image(VK_NULL_HANDLE), mem(VK_NULL_HANDLE), view(VK_NULL_HANDLE), tex_width(0), tex_height(0), numMips_(1), format_(VK_FORMAT_UNDEFINED), - mappableImage(VK_NULL_HANDLE), mappableMemory(VK_NULL_HANDLE), allocator_(allocator), offset_(0) { - memset(&mem_reqs, 0, sizeof(mem_reqs)); } ~VulkanTexture() { Destroy(); } - // Simple usage - no cleverness, no mipmaps. - // Always call Create, Lock, Unlock. Unlock performs the upload if necessary. - // Can later Lock and Unlock again. This cannot change the format. Create cannot - // be called a second time without recreating the texture object until Destroy has - // been called. - VkResult Create(int w, int h, VkFormat format); - uint8_t *Lock(int level, int *rowPitch); - void Unlock(VkCommandBuffer cmd); - // Fast uploads from buffer. Mipmaps supported. // Usage must at least include VK_IMAGE_USAGE_TRANSFER_DST_BIT in order to use UploadMip. // When using UploadMip, initialLayout should be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL. @@ -50,18 +39,14 @@ public: VkFormat GetFormat() const { return format_; } private: - void CreateMappableImage(); void Wipe(); VulkanContext *vulkan_; VkImage image; - VkDeviceMemory mem; VkImageView view; + VkDeviceMemory mem; int32_t tex_width, tex_height, numMips_; VkFormat format_; - VkImage mappableImage; - VkDeviceMemory mappableMemory; - VkMemoryRequirements mem_reqs; VulkanDeviceAllocator *allocator_; size_t offset_; }; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index d570aa8ce5..7c95f1388d 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -123,8 +123,6 @@ static UI::Theme ui_theme; #include "android/android-ndk-profiler/prof.h" #endif -std::unique_ptr uiTexture; - ScreenManager *screenManager; std::string config_filename; @@ -622,16 +620,6 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) { UIThemeInit(); - uiTexture = CreateTextureFromFile(g_draw, "ui_atlas.zim", ImageFileType::ZIM); - if (!uiTexture) { - PanicAlert("Failed to load ui_atlas.zim.\n\nPlace it in the directory \"assets\" under your PPSSPP directory."); - ELOG("Failed to load ui_atlas.zim"); -#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) - UINT ExitCode = 0; - ExitProcess(ExitCode); -#endif - } - uiContext = new UIContext(); uiContext->theme = &ui_theme; @@ -714,8 +702,6 @@ void NativeShutdownGraphics() { UIBackgroundShutdown(); - uiTexture.reset(nullptr); - delete uiContext; uiContext = nullptr; @@ -804,10 +790,6 @@ void RenderOverlays(UIContext *dc, void *userdata) { void NativeRender(GraphicsContext *graphicsContext) { g_GameManager.Update(); - // If uitexture gets reloaded, make sure we use the latest one. - // Not sure this happens anymore now that we tear down all graphics on app switches... - uiContext->FrameSetup(uiTexture->GetTexture()); - float xres = dp_xres; float yres = dp_yres; diff --git a/UI/TextureUtil.h b/UI/TextureUtil.h index 28a28b69d3..c71b1e39ba 100644 --- a/UI/TextureUtil.h +++ b/UI/TextureUtil.h @@ -3,7 +3,6 @@ #include #include "thin3d/thin3d.h" -#include "Core/Config.h" enum ImageFileType { PNG, diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 0fa38ecdf1..58cee3ee00 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -301,9 +301,9 @@ struct DescriptorSetKey { class VKTexture : public Texture { public: - VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, const TextureDesc &desc, VulkanDeviceAllocator *alloc) + VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc, VulkanDeviceAllocator *alloc) : vulkan_(vulkan), mipLevels_(desc.mipLevels), format_(desc.format) { - bool result = Create(cmd, desc, alloc); + bool result = Create(cmd, pushBuffer, desc, alloc); assert(result); } @@ -314,9 +314,7 @@ public: VkImageView GetImageView() { return vkTex_->GetImageView(); } private: - void SetImageData(VkCommandBuffer cmd, int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data); - - bool Create(VkCommandBuffer cmd, const TextureDesc &desc, VulkanDeviceAllocator *alloc); + bool Create(VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc, VulkanDeviceAllocator *alloc); void Destroy() { if (vkTex_) { @@ -650,20 +648,45 @@ enum class TextureState { PENDING_DESTRUCTION, }; -bool VKTexture::Create(VkCommandBuffer cmd, const TextureDesc &desc, VulkanDeviceAllocator *alloc) { +bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushBuffer *push, const TextureDesc &desc, VulkanDeviceAllocator *alloc) { // Zero-sized textures not allowed. assert(desc.width * desc.height * desc.depth > 0); + assert(push); format_ = desc.format; mipLevels_ = desc.mipLevels; width_ = desc.width; height_ = desc.height; depth_ = desc.depth; vkTex_ = new VulkanTexture(vulkan_, alloc); + VkFormat vulkanFormat = DataFormatToVulkan(format_); + int stride = desc.width * (int)DataFormatSizeInBytes(format_); + int bpp = GetBpp(vulkanFormat); + int bytesPerPixel = bpp / 8; + int usageBits = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + if (mipLevels_ > (int)desc.initData.size()) { + // Gonna have to generate some, which requires TRANSFER_SRC + usageBits |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + } + vkTex_->CreateDirect(cmd, width_, height_, mipLevels_, vulkanFormat, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, usageBits); if (desc.initData.size()) { - for (int i = 0; i < (int)desc.initData.size(); i++) { - this->SetImageData(cmd, 0, 0, 0, width_, height_, depth_, i, 0, desc.initData[i]); + int w = width_; + int h = height_; + int i; + for (i = 0; i < (int)desc.initData.size(); i++) { + uint32_t offset; + VkBuffer buf; + size_t size = w * h * bytesPerPixel; + offset = push->PushAligned((const void *)desc.initData[i], size, 16, &buf); + vkTex_->UploadMip(cmd, i, w, h, buf, offset, w); + w = (w + 1) / 2; + h = (h + 1) / 2; + } + // Generate the rest of the mips automatically. + for (; i < mipLevels_; i++) { + vkTex_->GenerateMip(cmd, i); } } + vkTex_->EndCreate(cmd, false); return true; } @@ -703,13 +726,13 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) dpTypes[1].descriptorCount = 200; dpTypes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - VkDescriptorPoolCreateInfo dp = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; + VkDescriptorPoolCreateInfo dp{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; dp.flags = 0; // Don't want to mess around with individually freeing these, let's go dynamic each frame. dp.maxSets = 200; // 200 textures per frame should be enough for the UI... dp.pPoolSizes = dpTypes; dp.poolSizeCount = ARRAY_SIZE(dpTypes); - VkCommandPoolCreateInfo p = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; + VkCommandPoolCreateInfo p{ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; p.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; p.queueFamilyIndex = vulkan->GetGraphicsQueueFamilyIndex(); @@ -994,23 +1017,7 @@ InputLayout *VKContext::CreateInputLayout(const InputLayoutDesc &desc) { } Texture *VKContext::CreateTexture(const TextureDesc &desc) { - return new VKTexture(vulkan_, renderManager_.GetInitCmd(), desc, allocator_); -} - -void VKTexture::SetImageData(VkCommandBuffer cmd, int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) { - VkFormat vulkanFormat = DataFormatToVulkan(format_); - if (stride == 0) { - stride = width * (int)DataFormatSizeInBytes(format_); - } - int bpp = GetBpp(vulkanFormat); - int bytesPerPixel = bpp / 8; - vkTex_->Create(width, height, vulkanFormat); - int rowPitch; - uint8_t *dstData = vkTex_->Lock(0, &rowPitch); - for (int y = 0; y < height; y++) { - memcpy(dstData + rowPitch * y, data + stride * y, width * bytesPerPixel); - } - vkTex_->Unlock(cmd); + return new VKTexture(vulkan_, renderManager_.GetInitCmd(), push_, desc, allocator_); } static inline void CopySide(VkStencilOpState &dest, const StencilSide &src) { diff --git a/ext/native/ui/ui_context.cpp b/ext/native/ui/ui_context.cpp index 671765a552..6ad2d78c8c 100644 --- a/ext/native/ui/ui_context.cpp +++ b/ext/native/ui/ui_context.cpp @@ -6,6 +6,8 @@ #include "gfx_es2/draw_buffer.h" #include "gfx_es2/draw_text.h" +#include "Common/Log.h" + UIContext::UIContext() { fontStyle_ = new UI::FontStyle(); bounds_ = Bounds(0, 0, dp_xres, dp_yres); @@ -28,13 +30,19 @@ void UIContext::Init(Draw::DrawContext *thin3d, Draw::Pipeline *uipipe, Draw::Pi textDrawer_ = TextDrawer::Create(thin3d); // May return nullptr if no implementation is available for this platform. } -void UIContext::FrameSetup(Draw::Texture *uiTexture) { - uitexture_ = uiTexture; +void UIContext::BeginFrame() { + if (!uitexture_) { + uitexture_ = CreateTextureFromFile(draw_, "ui_atlas.zim", ImageFileType::ZIM); + if (!uitexture_) { + PanicAlert("Failed to load ui_atlas.zim.\n\nPlace it in the directory \"assets\" under your PPSSPP directory."); + FLOG("Failed to load ui_atlas.zim"); + } + } } void UIContext::Begin() { draw_->BindSamplerStates(0, 1, &sampler_); - draw_->BindTexture(0, uitexture_); + draw_->BindTexture(0, uitexture_->GetTexture()); ActivateTopScissor(); UIBegin(ui_pipeline_); } @@ -45,7 +53,7 @@ void UIContext::BeginNoTex() { } void UIContext::RebindTexture() const { - draw_->BindTexture(0, uitexture_); + draw_->BindTexture(0, uitexture_->GetTexture()); } void UIContext::Flush() { diff --git a/ext/native/ui/ui_context.h b/ext/native/ui/ui_context.h index 59468abde7..3b6c4d7e43 100644 --- a/ext/native/ui/ui_context.h +++ b/ext/native/ui/ui_context.h @@ -6,6 +6,7 @@ #include "math/geom2d.h" #include "math/lin/vec3.h" #include "gfx/texture_atlas.h" +#include "UI/TextureUtil.h" // Everything you need to draw a UI collected into a single unit that can be passed around. // Everything forward declared so this header is safe everywhere. @@ -46,7 +47,7 @@ public: void Init(Draw::DrawContext *thin3d, Draw::Pipeline *uipipe, Draw::Pipeline *uipipenotex, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop); - void FrameSetup(Draw::Texture *uiTexture); + void BeginFrame(); void Begin(); void BeginNoTex(); @@ -102,7 +103,7 @@ private: Draw::SamplerState *sampler_; Draw::Pipeline *ui_pipeline_ = nullptr; Draw::Pipeline *ui_pipeline_notex_ = nullptr; - Draw::Texture *uitexture_ = nullptr; + std::unique_ptr uitexture_; DrawBuffer *uidrawbuffer_ = nullptr; DrawBuffer *uidrawbufferTop_ = nullptr; diff --git a/ext/native/ui/ui_screen.cpp b/ext/native/ui/ui_screen.cpp index 26e12b8b4f..092eacec1c 100644 --- a/ext/native/ui/ui_screen.cpp +++ b/ext/native/ui/ui_screen.cpp @@ -68,6 +68,7 @@ void UIScreen::preRender() { return; } draw->BeginFrame(); + screenManager()->getUIContext()->BeginFrame(); // Bind and clear the back buffer draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, 0xFF000000 }); From beeb9cc3a4c5cadcc05b09aa40d3361d12df0401 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 25 Feb 2018 12:45:13 -0800 Subject: [PATCH 179/291] GLES: Disable buffer mapping for non-NVIDIA. Need more stats on other vendors. I think it can help if we use it properly. --- ext/native/thin3d/GLRenderManager.cpp | 36 +++++++++++++++++---------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 2c3f0b1b58..efab8bf3fd 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -697,28 +697,38 @@ void GLPushBuffer::UnmapDevice() { void *GLRBuffer::Map(GLbitfield access) { assert(buffer != 0); - glBindBuffer(target_, buffer); + + // Notes on buffer mapping: + // NVIDIA GTX 9xx / 2017-10 drivers - mapping improves speed, explicit flush zero cost/benefit. + // PowerVR GX6xxx / iOS 10.3 - mapping has little improvement, explicit flush is slower. + // AMD / unknown - mapping causes black screens and flickering? + // Mali / unknown - mapping causes black screens and flickering? void *p = nullptr; - if (gl_extensions.ARB_buffer_storage || gl_extensions.EXT_buffer_storage) { + bool allowNativeBuffer = (gl_extensions.bugs & BUG_ANY_MAP_BUFFER_RANGE_SLOW) == 0; + if (allowNativeBuffer) { + glBindBuffer(target_, buffer); + + if (gl_extensions.ARB_buffer_storage || gl_extensions.EXT_buffer_storage) { #ifndef IOS - if (!hasStorage_) { + if (!hasStorage_) { #ifdef USING_GLES2 - glBufferStorageEXT(target_, size_, nullptr, access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); + glBufferStorageEXT(target_, size_, nullptr, access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); #else - glBufferStorage(target_, size_, nullptr, access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); + glBufferStorage(target_, size_, nullptr, access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); #endif - hasStorage_ = true; - } + hasStorage_ = true; + } #endif - p = glMapBufferRange(target_, 0, size_, access); - } else if (gl_extensions.VersionGEThan(3, 0, 0) && !(gl_extensions.bugs & BUG_ANY_MAP_BUFFER_RANGE_SLOW)) { - // GLES3 or desktop 3. - p = glMapBufferRange(target_, 0, size_, access); - } else if (!(gl_extensions.bugs & BUG_ANY_MAP_BUFFER_RANGE_SLOW)) { + p = glMapBufferRange(target_, 0, size_, access); + } else if (gl_extensions.VersionGEThan(3, 0, 0)) { + // GLES3 or desktop 3. + p = glMapBufferRange(target_, 0, size_, access); + } else { #ifndef USING_GLES2 - p = glMapBuffer(target_, GL_READ_WRITE); + p = glMapBuffer(target_, GL_READ_WRITE); #endif + } } mapped_ = p != nullptr; From eb73cc23cdfffc9a05acc67fd5310b096498c559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 09:26:07 +0100 Subject: [PATCH 180/291] Some log level changes. --- Common/FileUtil.cpp | 5 ++--- Core/ELF/PBPReader.cpp | 2 +- UI/GameInfoCache.cpp | 8 ++++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Common/FileUtil.cpp b/Common/FileUtil.cpp index 247163251b..1a9629f35b 100644 --- a/Common/FileUtil.cpp +++ b/Common/FileUtil.cpp @@ -241,10 +241,9 @@ bool CreateDir(const std::string &path) bool CreateFullPath(const std::string &fullPath) { int panicCounter = 100; - DEBUG_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str()); + VERBOSE_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str()); - if (File::Exists(fullPath)) - { + if (File::Exists(fullPath)) { DEBUG_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str()); return true; } diff --git a/Core/ELF/PBPReader.cpp b/Core/ELF/PBPReader.cpp index 1eb4f70556..76fdbb36e4 100644 --- a/Core/ELF/PBPReader.cpp +++ b/Core/ELF/PBPReader.cpp @@ -45,7 +45,7 @@ PBPReader::PBPReader(FileLoader *fileLoader) : file_(nullptr), header_(), isELF_ return; } - DEBUG_LOG(LOADER, "Loading PBP, version = %08x", header_.version); + VERBOSE_LOG(LOADER, "Loading PBP, version = %08x", header_.version); file_ = fileLoader; } diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 83b97f2b72..63e9c6efb9 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -460,13 +460,13 @@ handleELF: std::string screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) + info_->id + "_00000.jpg"; std::string screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) + info_->id + "_00000.png"; // Try using png/jpg screenshots first - if (File::Exists(screenshot_png)) + if (File::Exists(screenshot_png)) { readFileToString(false, screenshot_png.c_str(), info_->icon.data); - else if (File::Exists(screenshot_jpg)) + } else if (File::Exists(screenshot_jpg)) { readFileToString(false, screenshot_jpg.c_str(), info_->icon.data); - else { + } else { // Read standard icon - DEBUG_LOG(LOADER, "Loading unknown.png because there was an ELF"); + VERBOSE_LOG(LOADER, "Loading unknown.png because there was an ELF"); ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock); } info_->icon.dataLoaded = true; From 39bf5b1f558001ce645e407b147b67d062024756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 10:50:29 +0100 Subject: [PATCH 181/291] Minor naming and init cleanups in VulkanTexture --- Common/Vulkan/VulkanImage.cpp | 78 +++++++++++++++++------------------ Common/Vulkan/VulkanImage.h | 26 ++++++------ 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index fa5969ad3e..9551a1704a 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -3,17 +3,17 @@ #include "Common/Log.h" void VulkanTexture::Wipe() { - if (image) { - vulkan_->Delete().QueueDeleteImage(image); + if (image_) { + vulkan_->Delete().QueueDeleteImage(image_); } - if (view) { - vulkan_->Delete().QueueDeleteImageView(view); + if (view_) { + vulkan_->Delete().QueueDeleteImageView(view_); } - if (mem && !allocator_) { - vulkan_->Delete().QueueDeleteDeviceMemory(mem); - } else if (mem) { - allocator_->Free(mem, offset_); - mem = VK_NULL_HANDLE; + if (mem_ && !allocator_) { + vulkan_->Delete().QueueDeleteDeviceMemory(mem_); + } else if (mem_) { + allocator_->Free(mem_, offset_); + mem_ = VK_NULL_HANDLE; } } @@ -33,8 +33,8 @@ static bool IsDepthStencilFormat(VkFormat format) { bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage, const VkComponentMapping *mapping) { Wipe(); - tex_width = w; - tex_height = h; + width_ = w; + height_ = h; numMips_ = numMips; format_ = format; @@ -43,8 +43,8 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, VkImageCreateInfo image_create_info{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; image_create_info.imageType = VK_IMAGE_TYPE_2D; image_create_info.format = format_; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; + image_create_info.extent.width = width_; + image_create_info.extent.height = height_; image_create_info.extent.depth = 1; image_create_info.mipLevels = numMips; image_create_info.arrayLayers = 1; @@ -58,17 +58,17 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; } - VkResult res = vkCreateImage(vulkan_->GetDevice(), &image_create_info, NULL, &image); + VkResult res = vkCreateImage(vulkan_->GetDevice(), &image_create_info, NULL, &image_); if (res != VK_SUCCESS) { assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); return false; } VkMemoryRequirements mem_reqs{}; - vkGetImageMemoryRequirements(vulkan_->GetDevice(), image, &mem_reqs); + vkGetImageMemoryRequirements(vulkan_->GetDevice(), image_, &mem_reqs); if (allocator_) { - offset_ = allocator_->Allocate(mem_reqs, &mem); + offset_ = allocator_->Allocate(mem_reqs, &mem_); if (offset_ == VulkanDeviceAllocator::ALLOCATE_FAILED) { return false; } @@ -81,7 +81,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, bool pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mem_alloc.memoryTypeIndex); assert(pass); - res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mem); + res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mem_); if (res != VK_SUCCESS) { _assert_msg_(G3D, res != VK_ERROR_TOO_MANY_OBJECTS, "Too many Vulkan memory objects!"); assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); @@ -91,7 +91,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, offset_ = 0; } - res = vkBindImageMemory(vulkan_->GetDevice(), image, mem, offset_); + res = vkBindImageMemory(vulkan_->GetDevice(), image_, mem_, offset_); if (res != VK_SUCCESS) { assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); return false; @@ -101,7 +101,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, if (initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) { switch (initialLayout) { case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - TransitionImageLayout2(cmd, image, 0, numMips, VK_IMAGE_ASPECT_COLOR_BIT, + TransitionImageLayout2(cmd, image_, 0, numMips, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT); @@ -116,7 +116,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, // Create the view while we're at it. VkImageViewCreateInfo view_info{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; - view_info.image = image; + view_info.image = image_; view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; view_info.format = format_; if (mapping) { @@ -133,7 +133,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, view_info.subresourceRange.baseArrayLayer = 0; view_info.subresourceRange.layerCount = 1; - res = vkCreateImageView(vulkan_->GetDevice(), &view_info, NULL, &view); + res = vkCreateImageView(vulkan_->GetDevice(), &view_info, NULL, &view_); if (res != VK_SUCCESS) { assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); return false; @@ -154,7 +154,7 @@ void VulkanTexture::UploadMip(VkCommandBuffer cmd, int mip, int mipWidth, int mi copy_region.imageSubresource.baseArrayLayer = 0; copy_region.imageSubresource.layerCount = 1; - vkCmdCopyBufferToImage(cmd, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); + vkCmdCopyBufferToImage(cmd, buffer, image_, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); } void VulkanTexture::GenerateMip(VkCommandBuffer cmd, int mip) { @@ -164,33 +164,33 @@ void VulkanTexture::GenerateMip(VkCommandBuffer cmd, int mip) { blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blit.srcSubresource.layerCount = 1; blit.srcSubresource.mipLevel = mip - 1; - blit.srcOffsets[1].x = tex_width >> (mip - 1); - blit.srcOffsets[1].y = tex_height >> (mip - 1); + blit.srcOffsets[1].x = width_ >> (mip - 1); + blit.srcOffsets[1].y = height_ >> (mip - 1); blit.srcOffsets[1].z = 1; blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blit.dstSubresource.layerCount = 1; blit.dstSubresource.mipLevel = mip; - blit.dstOffsets[1].x = tex_width >> mip; - blit.dstOffsets[1].y = tex_height >> mip; + blit.dstOffsets[1].x = width_ >> mip; + blit.dstOffsets[1].y = height_ >> mip; blit.dstOffsets[1].z = 1; - TransitionImageLayout2(cmd, image, mip - 1, 1, VK_IMAGE_ASPECT_COLOR_BIT, + TransitionImageLayout2(cmd, image_, mip - 1, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT); // Low-quality mipmap generation, but works okay. - vkCmdBlitImage(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR); + vkCmdBlitImage(cmd, image_, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image_, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR); - TransitionImageLayout2(cmd, image, mip - 1, 1, VK_IMAGE_ASPECT_COLOR_BIT, + TransitionImageLayout2(cmd, image_, mip - 1, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT); } void VulkanTexture::EndCreate(VkCommandBuffer cmd, bool vertexTexture) { - TransitionImageLayout2(cmd, image, 0, 1, + TransitionImageLayout2(cmd, image_, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, vertexTexture ? VK_PIPELINE_STAGE_VERTEX_SHADER_BIT : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, @@ -198,16 +198,16 @@ void VulkanTexture::EndCreate(VkCommandBuffer cmd, bool vertexTexture) { } void VulkanTexture::Destroy() { - if (view != VK_NULL_HANDLE) { - vulkan_->Delete().QueueDeleteImageView(view); + if (view_ != VK_NULL_HANDLE) { + vulkan_->Delete().QueueDeleteImageView(view_); } - if (image != VK_NULL_HANDLE) { - vulkan_->Delete().QueueDeleteImage(image); + if (image_ != VK_NULL_HANDLE) { + vulkan_->Delete().QueueDeleteImage(image_); } - if (mem != VK_NULL_HANDLE && !allocator_) { - vulkan_->Delete().QueueDeleteDeviceMemory(mem); - } else if (mem != VK_NULL_HANDLE) { - allocator_->Free(mem, offset_); - mem = VK_NULL_HANDLE; + if (mem_ != VK_NULL_HANDLE && !allocator_) { + vulkan_->Delete().QueueDeleteDeviceMemory(mem_); + } else if (mem_ != VK_NULL_HANDLE) { + allocator_->Free(mem_, offset_); + mem_ = VK_NULL_HANDLE; } } diff --git a/Common/Vulkan/VulkanImage.h b/Common/Vulkan/VulkanImage.h index df2a45edd1..14c347078c 100644 --- a/Common/Vulkan/VulkanImage.h +++ b/Common/Vulkan/VulkanImage.h @@ -9,9 +9,7 @@ class VulkanDeviceAllocator; class VulkanTexture { public: VulkanTexture(VulkanContext *vulkan, VulkanDeviceAllocator *allocator) - : vulkan_(vulkan), image(VK_NULL_HANDLE), mem(VK_NULL_HANDLE), view(VK_NULL_HANDLE), - tex_width(0), tex_height(0), numMips_(1), format_(VK_FORMAT_UNDEFINED), - allocator_(allocator), offset_(0) { + : vulkan_(vulkan), allocator_(allocator) { } ~VulkanTexture() { Destroy(); @@ -28,13 +26,13 @@ public: void Destroy(); // Used in image copies, etc. - VkImage GetImage() const { return image; } + VkImage GetImage() const { return image_; } // Used for sampling, generally. - VkImageView GetImageView() const { return view; } + VkImageView GetImageView() const { return view_; } - int32_t GetWidth() const { return tex_width; } - int32_t GetHeight() const { return tex_height; } + int32_t GetWidth() const { return width_; } + int32_t GetHeight() const { return height_; } int32_t GetNumMips() const { return numMips_; } VkFormat GetFormat() const { return format_; } @@ -42,11 +40,13 @@ private: void Wipe(); VulkanContext *vulkan_; - VkImage image; - VkImageView view; - VkDeviceMemory mem; - int32_t tex_width, tex_height, numMips_; - VkFormat format_; + VkImage image_ = VK_NULL_HANDLE; + VkImageView view_ = VK_NULL_HANDLE; + VkDeviceMemory mem_ = VK_NULL_HANDLE; + int32_t width_ = 0; + int32_t height_ = 0; + int32_t numMips_ = 1; + VkFormat format_ = VK_FORMAT_UNDEFINED; VulkanDeviceAllocator *allocator_; - size_t offset_; + size_t offset_ = 0; }; From 23980065ba7eb14a5b2c13d4a11d0aec93d00eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 11:02:52 +0100 Subject: [PATCH 182/291] Unify all the DrawEngine::SubmitPrim --- GPU/Common/DrawEngineCommon.cpp | 66 +++++++++++++++++++++++++++++++++ GPU/Common/DrawEngineCommon.h | 2 + GPU/D3D11/DrawEngineD3D11.cpp | 66 --------------------------------- GPU/D3D11/DrawEngineD3D11.h | 2 - GPU/Directx9/DrawEngineDX9.cpp | 64 -------------------------------- GPU/Directx9/DrawEngineDX9.h | 2 - GPU/GLES/DrawEngineGLES.cpp | 64 -------------------------------- GPU/GLES/DrawEngineGLES.h | 2 - GPU/Vulkan/DrawEngineVulkan.cpp | 66 --------------------------------- GPU/Vulkan/DrawEngineVulkan.h | 2 - 10 files changed, 68 insertions(+), 268 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 4ea75b7d16..1f6a44eda2 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -668,3 +668,69 @@ ReliableHashType DrawEngineCommon::ComputeHash() { fullhash += DoReliableHash(&uvScale[0], sizeof(uvScale[0]) * numDrawCalls, 0x0123e658); return fullhash; } + +void DrawEngineCommon::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) { + if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawCalls >= MAX_DEFERRED_DRAW_CALLS || vertexCountInDrawCalls_ + vertexCount > VERTEX_BUFFER_MAX) { + DispatchFlush(); + } + + // TODO: Is this the right thing to do? + if (prim == GE_PRIM_KEEP_PREVIOUS) { + prim = prevPrim_ != GE_PRIM_INVALID ? prevPrim_ : GE_PRIM_POINTS; + } else { + prevPrim_ = prim; + } + + SetupVertexDecoder(vertType); + + *bytesRead = vertexCount * dec_->VertexSize(); + if ((vertexCount < 2 && prim > 0) || (vertexCount < 3 && prim > 2 && prim != GE_PRIM_RECTANGLES)) + return; + + DeferredDrawCall &dc = drawCalls[numDrawCalls]; + dc.verts = verts; + dc.inds = inds; + dc.vertType = vertType; + dc.indexType = (vertType & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT; + dc.prim = prim; + dc.vertexCount = vertexCount; + + if (g_Config.bVertexCache) { + u32 dhash = dcid_; + dhash ^= (u32)(uintptr_t)verts; + dhash = __rotl(dhash, 13); + dhash ^= (u32)(uintptr_t)inds; + dhash = __rotl(dhash, 13); + dhash ^= (u32)vertType; + dhash = __rotl(dhash, 13); + dhash ^= (u32)vertexCount; + dhash = __rotl(dhash, 13); + dhash ^= (u32)prim; + dcid_ = dhash; + } + + if (inds) { + GetIndexBounds(inds, vertexCount, vertType, &dc.indexLowerBound, &dc.indexUpperBound); + } else { + dc.indexLowerBound = 0; + dc.indexUpperBound = vertexCount - 1; + } + + uvScale[numDrawCalls] = gstate_c.uv; + + numDrawCalls++; + vertexCountInDrawCalls_ += vertexCount; + + if (g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK)) { + DecodeVertsStep(decoded, decodeCounter_, decodedVerts_); + decodeCounter_++; + } + + if (prim == GE_PRIM_RECTANGLES && (gstate.getTextureAddress(0) & 0x3FFFFFFF) == (gstate.getFrameBufAddress() & 0x3FFFFFFF)) { + // Rendertarget == texture? + if (!g_Config.bDisableSlowFramebufEffects) { + gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); + DispatchFlush(); + } + } +} diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 24599a094b..25eb441b06 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -60,6 +60,8 @@ public: virtual void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) = 0; bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType, int *bytesRead); + + void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead); void SubmitSpline(const void *control_points, const void *indices, int tess_u, int tess_v, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, bool computeNormals, bool patchFacing, u32 vertType, int *bytesRead); void SubmitBezier(const void *control_points, const void *indices, int tess_u, int tess_v, int count_u, int count_v, GEPatchPrimType prim_type, bool computeNormals, bool patchFacing, u32 vertType, int *bytesRead); diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 9924d9c888..2b49ae2d6e 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -257,72 +257,6 @@ ID3D11InputLayout *DrawEngineD3D11::SetupDecFmtForDraw(D3D11VertexShader *vshade } } -void DrawEngineD3D11::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) { - if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawCalls >= MAX_DEFERRED_DRAW_CALLS || vertexCountInDrawCalls_ + vertexCount > VERTEX_BUFFER_MAX) - Flush(); - - // TODO: Is this the right thing to do? - if (prim == GE_PRIM_KEEP_PREVIOUS) { - prim = prevPrim_ != GE_PRIM_INVALID ? prevPrim_ : GE_PRIM_POINTS; - } else { - prevPrim_ = prim; - } - - SetupVertexDecoder(vertType); - - *bytesRead = vertexCount * dec_->VertexSize(); - - if ((vertexCount < 2 && prim > 0) || (vertexCount < 3 && prim > 2 && prim != GE_PRIM_RECTANGLES)) - return; - - DeferredDrawCall &dc = drawCalls[numDrawCalls]; - dc.verts = verts; - dc.inds = inds; - dc.vertType = vertType; - dc.indexType = (vertType & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT; - dc.prim = prim; - dc.vertexCount = vertexCount; - - if (g_Config.bVertexCache) { - u32 dhash = dcid_; - dhash ^= (u32)(uintptr_t)verts; - dhash = __rotl(dhash, 13); - dhash ^= (u32)(uintptr_t)inds; - dhash = __rotl(dhash, 13); - dhash ^= (u32)vertType; - dhash = __rotl(dhash, 13); - dhash ^= (u32)vertexCount; - dhash = __rotl(dhash, 13); - dhash ^= (u32)prim; - dcid_ = dhash; - } - - if (inds) { - GetIndexBounds(inds, vertexCount, vertType, &dc.indexLowerBound, &dc.indexUpperBound); - } else { - dc.indexLowerBound = 0; - dc.indexUpperBound = vertexCount - 1; - } - - uvScale[numDrawCalls] = gstate_c.uv; - - numDrawCalls++; - vertexCountInDrawCalls_ += vertexCount; - - if (g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK)) { - DecodeVertsStep(decoded, decodeCounter_, decodedVerts_); - decodeCounter_++; - } - - if (prim == GE_PRIM_RECTANGLES && (gstate.getTextureAddress(0) & 0x3FFFFFFF) == (gstate.getFrameBufAddress() & 0x3FFFFFFF)) { - // Rendertarget == texture? - if (!g_Config.bDisableSlowFramebufEffects) { - gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - Flush(); - } - } -} - void DrawEngineD3D11::MarkUnreliable(VertexArrayInfoD3D11 *vai) { vai->status = VertexArrayInfoD3D11::VAI_UNRELIABLE; if (vai->vbo) { diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index 6928bca67b..3a88d7ae97 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -105,8 +105,6 @@ public: DrawEngineD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context); virtual ~DrawEngineD3D11(); - void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead); - void SetShaderManager(ShaderManagerD3D11 *shaderManager) { shaderManager_ = shaderManager; } diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 1acd41d7a3..c72d256727 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -232,70 +232,6 @@ IDirect3DVertexDeclaration9 *DrawEngineDX9::SetupDecFmtForDraw(VSShader *vshader } } -void DrawEngineDX9::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) { - if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawCalls >= MAX_DEFERRED_DRAW_CALLS || vertexCountInDrawCalls_ + vertexCount > VERTEX_BUFFER_MAX) - Flush(); - - // TODO: Is this the right thing to do? - if (prim == GE_PRIM_KEEP_PREVIOUS) { - prim = prevPrim_ != GE_PRIM_INVALID ? prevPrim_ : GE_PRIM_POINTS; - } else { - prevPrim_ = prim; - } - - SetupVertexDecoder(vertType); - - *bytesRead = vertexCount * dec_->VertexSize(); - - if ((vertexCount < 2 && prim > 0) || (vertexCount < 3 && prim > 2 && prim != GE_PRIM_RECTANGLES)) - return; - - DeferredDrawCall &dc = drawCalls[numDrawCalls]; - dc.verts = verts; - dc.inds = inds; - dc.vertType = vertType; - dc.indexType = (vertType & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT; - dc.prim = prim; - dc.vertexCount = vertexCount; - - u32 dhash = dcid_; - dhash ^= (u32)(uintptr_t)verts; - dhash = __rotl(dhash, 13); - dhash ^= (u32)(uintptr_t)inds; - dhash = __rotl(dhash, 13); - dhash ^= (u32)vertType; - dhash = __rotl(dhash, 13); - dhash ^= (u32)vertexCount; - dhash = __rotl(dhash, 13); - dhash ^= (u32)prim; - dcid_ = dhash; - - if (inds) { - GetIndexBounds(inds, vertexCount, vertType, &dc.indexLowerBound, &dc.indexUpperBound); - } else { - dc.indexLowerBound = 0; - dc.indexUpperBound = vertexCount - 1; - } - - uvScale[numDrawCalls] = gstate_c.uv; - - numDrawCalls++; - vertexCountInDrawCalls_ += vertexCount; - - if (g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK)) { - DecodeVertsStep(decoded, decodeCounter_, decodedVerts_); - decodeCounter_++; - } - - if (prim == GE_PRIM_RECTANGLES && (gstate.getTextureAddress(0) & 0x3FFFFFFF) == (gstate.getFrameBufAddress() & 0x3FFFFFFF)) { - // Rendertarget == texture? - if (!g_Config.bDisableSlowFramebufEffects) { - gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - Flush(); - } - } -} - void DrawEngineDX9::MarkUnreliable(VertexArrayInfoDX9 *vai) { vai->status = VertexArrayInfoDX9::VAI_UNRELIABLE; if (vai->vbo) { diff --git a/GPU/Directx9/DrawEngineDX9.h b/GPU/Directx9/DrawEngineDX9.h index 35cc5fd18e..171675f3e0 100644 --- a/GPU/Directx9/DrawEngineDX9.h +++ b/GPU/Directx9/DrawEngineDX9.h @@ -103,8 +103,6 @@ public: DrawEngineDX9(Draw::DrawContext *draw); virtual ~DrawEngineDX9(); - void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead); - void SetShaderManager(ShaderManagerDX9 *shaderManager) { shaderManager_ = shaderManager; } diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index bb0676719c..83b56e5cab 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -276,70 +276,6 @@ GLRInputLayout *DrawEngineGLES::SetupDecFmtForDraw(LinkedShader *program, const return inputLayout; } -void DrawEngineGLES::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) { - if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawCalls >= MAX_DEFERRED_DRAW_CALLS || vertexCountInDrawCalls_ + vertexCount > VERTEX_BUFFER_MAX) - Flush(); - - // TODO: Is this the right thing to do? - if (prim == GE_PRIM_KEEP_PREVIOUS) { - prim = prevPrim_ != GE_PRIM_INVALID ? prevPrim_ : GE_PRIM_POINTS; - } else { - prevPrim_ = prim; - } - - SetupVertexDecoder(vertType); - - *bytesRead = vertexCount * dec_->VertexSize(); - - if ((vertexCount < 2 && prim > 0) || (vertexCount < 3 && prim > 2 && prim != GE_PRIM_RECTANGLES)) - return; - - DeferredDrawCall &dc = drawCalls[numDrawCalls]; - dc.verts = verts; - dc.inds = inds; - dc.vertType = vertType; - dc.indexType = (vertType & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT; - dc.prim = prim; - dc.vertexCount = vertexCount; - - u32 dhash = dcid_; - dhash ^= (u32)(uintptr_t)verts; - dhash = __rotl(dhash, 13); - dhash ^= (u32)(uintptr_t)inds; - dhash = __rotl(dhash, 13); - dhash ^= (u32)vertType; - dhash = __rotl(dhash, 13); - dhash ^= (u32)vertexCount; - dhash = __rotl(dhash, 13); - dhash ^= (u32)prim; - dcid_ = dhash; - - if (inds) { - GetIndexBounds(inds, vertexCount, vertType, &dc.indexLowerBound, &dc.indexUpperBound); - } else { - dc.indexLowerBound = 0; - dc.indexUpperBound = vertexCount - 1; - } - - uvScale[numDrawCalls] = gstate_c.uv; - - numDrawCalls++; - vertexCountInDrawCalls_ += vertexCount; - - if (g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK)) { - DecodeVertsStep(decoded, decodeCounter_, decodedVerts_); - decodeCounter_++; - } - - if (prim == GE_PRIM_RECTANGLES && (gstate.getTextureAddress(0) & 0x3FFFFFFF) == (gstate.getFrameBufAddress() & 0x3FFFFFFF)) { - // Rendertarget == texture? - if (!g_Config.bDisableSlowFramebufEffects) { - gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - Flush(); - } - } -} - void DrawEngineGLES::DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bindOffset, GLRBuffer **buf) { u8 *dest = decoded; diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 59246fb5cd..62340af75c 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -105,8 +105,6 @@ public: DrawEngineGLES(Draw::DrawContext *draw); virtual ~DrawEngineGLES(); - void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead); - void SetShaderManager(ShaderManagerGLES *shaderManager) { shaderManager_ = shaderManager; } diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 122b50ddaa..faba817b1c 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -337,72 +337,6 @@ void DrawEngineVulkan::EndFrame() { vertexCache_->End(); } -void DrawEngineVulkan::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) { - if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawCalls >= MAX_DEFERRED_DRAW_CALLS || vertexCountInDrawCalls_ + vertexCount > VERTEX_BUFFER_MAX) { - Flush(); - } - - // TODO: Is this the right thing to do? - if (prim == GE_PRIM_KEEP_PREVIOUS) { - prim = prevPrim_ != GE_PRIM_INVALID ? prevPrim_ : GE_PRIM_POINTS; - } else { - prevPrim_ = prim; - } - - SetupVertexDecoder(vertType); - - *bytesRead = vertexCount * dec_->VertexSize(); - if ((vertexCount < 2 && prim > 0) || (vertexCount < 3 && prim > 2 && prim != GE_PRIM_RECTANGLES)) - return; - - DeferredDrawCall &dc = drawCalls[numDrawCalls]; - dc.verts = verts; - dc.inds = inds; - dc.vertType = vertType; - dc.indexType = (vertType & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT; - dc.prim = prim; - dc.vertexCount = vertexCount; - - if (g_Config.bVertexCache) { - u32 dhash = dcid_; - dhash ^= (u32)(uintptr_t)verts; - dhash = __rotl(dhash, 13); - dhash ^= (u32)(uintptr_t)inds; - dhash = __rotl(dhash, 13); - dhash ^= (u32)vertType; - dhash = __rotl(dhash, 13); - dhash ^= (u32)vertexCount; - dhash = __rotl(dhash, 13); - dhash ^= (u32)prim; - dcid_ = dhash; - } - - if (inds) { - GetIndexBounds(inds, vertexCount, vertType, &dc.indexLowerBound, &dc.indexUpperBound); - } else { - dc.indexLowerBound = 0; - dc.indexUpperBound = vertexCount - 1; - } - - uvScale[numDrawCalls] = gstate_c.uv; - - numDrawCalls++; - vertexCountInDrawCalls_ += vertexCount; - - if (g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK)) { - DecodeVertsStep(decoded, decodeCounter_, decodedVerts_); - decodeCounter_++; - } - - if (prim == GE_PRIM_RECTANGLES && (gstate.getTextureAddress(0) & 0x3FFFFFFF) == (gstate.getFrameBufAddress() & 0x3FFFFFFF)) { - // Rendertarget == texture? - if (!g_Config.bDisableSlowFramebufEffects) { - gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - Flush(); - } - } -} - void DrawEngineVulkan::DecodeVertsToPushBuffer(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf) { u8 *dest = decoded; diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 15890cefde..a80f05a5d9 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -122,8 +122,6 @@ public: DrawEngineVulkan(VulkanContext *vulkan, Draw::DrawContext *draw); virtual ~DrawEngineVulkan(); - void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead); - void SetShaderManager(ShaderManagerVulkan *shaderManager) { shaderManager_ = shaderManager; } From c7f8f4c5cac059e44c7fe873842d2f6d7c82c3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 11:18:52 +0100 Subject: [PATCH 183/291] Unify Execute_Prim --- GPU/D3D11/GPU_D3D11.cpp | 85 +------------------------------------ GPU/D3D11/GPU_D3D11.h | 1 - GPU/Directx9/GPU_DX9.cpp | 88 --------------------------------------- GPU/Directx9/GPU_DX9.h | 2 - GPU/GLES/GPU_GLES.cpp | 82 +----------------------------------- GPU/GPUCommon.cpp | 84 ++++++++++++++++++++++++++++++++++++- GPU/GPUCommon.h | 3 ++ GPU/Vulkan/GPU_Vulkan.cpp | 86 +------------------------------------- GPU/Vulkan/GPU_Vulkan.h | 3 -- 9 files changed, 89 insertions(+), 345 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 24dcfdd734..e11a6dec2d 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -75,16 +75,6 @@ struct D3D11CommandTableEntry { // This table gets crunched into a faster form by init. static const D3D11CommandTableEntry commandTable[] = { - // Changes that dirty the current texture. - { GE_CMD_TEXSIZE0, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_TexSize0 }, - - // Changing the vertex type requires us to flush. - { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_VertexType }, - - { GE_CMD_PRIM, FLAG_EXECUTE, 0, &GPU_D3D11::Execute_Prim }, - { GE_CMD_BEZIER, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPUCommon::Execute_Bezier }, - { GE_CMD_SPLINE, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPUCommon::Execute_Spline }, - // Changes that trigger data copies. Only flushing on change for LOADCLUT must be a bit of a hack... { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPU_D3D11::Execute_LoadClut }, }; @@ -435,82 +425,9 @@ void GPU_D3D11::ExecuteOp(u32 op, u32 diff) { } } -void GPU_D3D11::Execute_Prim(u32 op, u32 diff) { - // This drives all drawing. All other state we just buffer up, then we apply it only - // when it's time to draw. As most PSP games set state redundantly ALL THE TIME, this is a huge optimization. - - u32 data = op & 0xFFFFFF; - u32 count = data & 0xFFFF; - if (count == 0) - return; - - // Upper bits are ignored. - GEPrimitiveType prim = static_cast((data >> 16) & 7); - SetDrawType(DRAW_PRIM, prim); - - // Discard AA lines as we can't do anything that makes sense with these anyway. The SW plugin might, though. - - if (gstate.isAntiAliasEnabled()) { - // Discard AA lines in DOA - if (prim == GE_PRIM_LINE_STRIP) - return; - // Discard AA lines in Summon Night 5 - if ((prim == GE_PRIM_LINES) && gstate.isSkinningEnabled()) - return; - } - - // This also make skipping drawing very effective. - framebufferManagerD3D11_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); - if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { - drawEngine_.SetupVertexDecoder(gstate.vertType); - // Rough estimate, not sure what's correct. - cyclesExecuted += EstimatePerVertexCost() * count; - return; - } - - u32 vertexAddr = gstate_c.vertexAddr; - if (!Memory::IsValidAddress(vertexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad vertex address %08x!", vertexAddr); - return; - } - - void *verts = Memory::GetPointerUnchecked(vertexAddr); - void *inds = 0; - u32 vertexType = gstate.vertType; - if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { - u32 indexAddr = gstate_c.indexAddr; - if (!Memory::IsValidAddress(indexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad index address %08x!", indexAddr); - return; - } - inds = Memory::GetPointerUnchecked(indexAddr); - } - -#ifndef MOBILE_DEVICE - if (prim > GE_PRIM_RECTANGLES) { - ERROR_LOG_REPORT_ONCE(reportPrim, G3D, "Unexpected prim type: %d", prim); - } -#endif - - if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) { - vertexCost_ = EstimatePerVertexCost(); - } - gpuStats.vertexGPUCycles += vertexCost_ * count; - cyclesExecuted += vertexCost_* count; - - int bytesRead = 0; - UpdateUVScaleOffset(); - drawEngine_.SubmitPrim(verts, inds, prim, count, vertexType, &bytesRead); - - // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). - // Some games rely on this, they don't bother reloading VADDR and IADDR. - // The VADDR/IADDR registers are NOT updated. - AdvanceVerts(vertexType, count, bytesRead); -} - void GPU_D3D11::Execute_LoadClut(u32 op, u32 diff) { gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - textureCacheD3D11_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); + textureCache_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); // This could be used to "dirty" textures with clut. } diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index f2dea31c61..0719144feb 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -64,7 +64,6 @@ public: GPU_D3D11::CmdFunc func; }; - void Execute_Prim(u32 op, u32 diff); void Execute_LoadClut(u32 op, u32 diff); // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 158442285c..04b2f0ddda 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -59,16 +59,6 @@ struct D3D9CommandTableEntry { // This table gets crunched into a faster form by init. static const D3D9CommandTableEntry commandTable[] = { - // Changes that dirty the current texture. - { GE_CMD_TEXSIZE0, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_TexSize0 }, - - // Changing the vertex type requires us to flush. - { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_VertexType }, - - { GE_CMD_PRIM, FLAG_EXECUTE, 0, &GPU_DX9::Execute_Prim }, - { GE_CMD_BEZIER, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPUCommon::Execute_Bezier }, - { GE_CMD_SPLINE, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPUCommon::Execute_Spline }, - // Changes that trigger data copies. Only flushing on change for LOADCLUT must be a bit of a hack... { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPU_DX9::Execute_LoadClut }, }; @@ -410,84 +400,6 @@ void GPU_DX9::ExecuteOp(u32 op, u32 diff) { } } -void GPU_DX9::Execute_Prim(u32 op, u32 diff) { - // This drives all drawing. All other state we just buffer up, then we apply it only - // when it's time to draw. As most PSP games set state redundantly ALL THE TIME, this is a huge optimization. - - u32 data = op & 0xFFFFFF; - u32 count = data & 0xFFFF; - if (count == 0) - return; - // Upper bits are ignored. - GEPrimitiveType prim = static_cast((data >> 16) & 7); - SetDrawType(DRAW_PRIM, prim); - - // Discard AA lines as we can't do anything that makes sense with these anyway. The SW plugin might, though. - - if (gstate.isAntiAliasEnabled()) { - // Discard AA lines in DOA - if (prim == GE_PRIM_LINE_STRIP) - return; - // Discard AA lines in Summon Night 5 - if ((prim == GE_PRIM_LINES) && gstate.isSkinningEnabled()) - return; - } - - // This also make skipping drawing very effective. - framebufferManagerDX9_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); - if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { - drawEngine_.SetupVertexDecoder(gstate.vertType); - // Rough estimate, not sure what's correct. - cyclesExecuted += EstimatePerVertexCost() * count; - return; - } - - u32 vertexAddr = gstate_c.vertexAddr; - if (!Memory::IsValidAddress(vertexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad vertex address %08x!", vertexAddr); - return; - } - - void *verts = Memory::GetPointerUnchecked(vertexAddr); - void *inds = 0; - u32 vertexType = gstate.vertType; - if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { - u32 indexAddr = gstate_c.indexAddr; - if (!Memory::IsValidAddress(indexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad index address %08x!", indexAddr); - return; - } - inds = Memory::GetPointerUnchecked(indexAddr); - } - -#ifndef MOBILE_DEVICE - if (prim > GE_PRIM_RECTANGLES) { - ERROR_LOG_REPORT_ONCE(reportPrim, G3D, "Unexpected prim type: %d", prim); - } -#endif - - if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) { - vertexCost_ = EstimatePerVertexCost(); - } - gpuStats.vertexGPUCycles += vertexCost_ * count; - cyclesExecuted += vertexCost_* count; - - int bytesRead = 0; - UpdateUVScaleOffset(); - drawEngine_.SubmitPrim(verts, inds, prim, count, vertexType, &bytesRead); - - // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). - // Some games rely on this, they don't bother reloading VADDR and IADDR. - // The VADDR/IADDR registers are NOT updated. - AdvanceVerts(vertexType, count, bytesRead); -} - -void GPU_DX9::Execute_LoadClut(u32 op, u32 diff) { - gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - textureCacheDX9_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); - // This could be used to "dirty" textures with clut. -} - void GPU_DX9::GetStats(char *buffer, size_t bufsize) { float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f; snprintf(buffer, bufsize - 1, diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 1a0a7ee037..30f661696f 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -65,8 +65,6 @@ public: GPU_DX9::CmdFunc func; }; - void Execute_Prim(u32 op, u32 diff); - void Execute_TexSize0(u32 op, u32 diff); void Execute_LoadClut(u32 op, u32 diff); // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 4ca8419772..8ec5f19103 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -61,16 +61,6 @@ struct GLESCommandTableEntry { // This table gets crunched into a faster form by init. // TODO: Share this table between the backends. Will have to make another indirection for the function pointers though.. static const GLESCommandTableEntry commandTable[] = { - // Changes that dirty the current texture. - { GE_CMD_TEXSIZE0, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_TexSize0 }, - - // Changing the vertex type requires us to flush. - { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_VertexType }, - - { GE_CMD_PRIM, FLAG_EXECUTE, 0, &GPU_GLES::Execute_Prim }, - { GE_CMD_BEZIER, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPUCommon::Execute_Bezier }, - { GE_CMD_SPLINE, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPUCommon::Execute_Spline }, - // Changes that trigger data copies. Only flushing on change for LOADCLUT must be a bit of a hack... { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPU_GLES::Execute_LoadClut }, }; @@ -625,79 +615,9 @@ void GPU_GLES::ExecuteOp(u32 op, u32 diff) { } } -void GPU_GLES::Execute_Prim(u32 op, u32 diff) { - // This drives all drawing. All other state we just buffer up, then we apply it only - // when it's time to draw. As most PSP games set state redundantly ALL THE TIME, this is a huge optimization. - - u32 data = op & 0xFFFFFF; - u32 count = data & 0xFFFF; - if (count == 0) - return; - - // Upper bits are ignored. - GEPrimitiveType prim = static_cast((data >> 16) & 7); - SetDrawType(DRAW_PRIM, prim); - - // Discard AA lines as we can't do anything that makes sense with these anyway. The SW plugin might, though. - - if (gstate.isAntiAliasEnabled()) { - // Discard AA lines in DOA - if (prim == GE_PRIM_LINE_STRIP) - return; - // Discard AA lines in Summon Night 5 - if ((prim == GE_PRIM_LINES) && gstate.isSkinningEnabled()) - return; - } - - // This also makes skipping drawing very effective. This function can change the framebuffer. - framebufferManagerGL_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); - if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { - drawEngine_.SetupVertexDecoder(gstate.vertType); - // Rough estimate, not sure what's correct. - cyclesExecuted += EstimatePerVertexCost() * count; - return; - } - - if (!Memory::IsValidAddress(gstate_c.vertexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad vertex address %08x!", gstate_c.vertexAddr); - return; - } - - void *verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); - void *inds = 0; - if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { - if (!Memory::IsValidAddress(gstate_c.indexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad index address %08x!", gstate_c.indexAddr); - return; - } - inds = Memory::GetPointerUnchecked(gstate_c.indexAddr); - } - -#ifndef MOBILE_DEVICE - if (prim > GE_PRIM_RECTANGLES) { - ERROR_LOG_REPORT_ONCE(reportPrim, G3D, "Unexpected prim type: %d", prim); - } -#endif - - if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) { - vertexCost_ = EstimatePerVertexCost(); - } - gpuStats.vertexGPUCycles += vertexCost_ * count; - cyclesExecuted += vertexCost_* count; - - int bytesRead = 0; - UpdateUVScaleOffset(); - drawEngine_.SubmitPrim(verts, inds, prim, count, gstate.vertType, &bytesRead); - - // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). - // Some games rely on this, they don't bother reloading VADDR and IADDR. - // The VADDR/IADDR registers are NOT updated. - AdvanceVerts(gstate.vertType, count, bytesRead); -} - void GPU_GLES::Execute_LoadClut(u32 op, u32 diff) { gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - textureCacheGL_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); + textureCache_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); } void GPU_GLES::GetStats(char *buffer, size_t bufsize) { diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index af99023ced..16ecf8c23a 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -42,6 +42,13 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_BJUMP, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_BJump }, // EXECUTE { GE_CMD_BOUNDINGBOX, FLAG_EXECUTE, 0, &GPUCommon::Execute_BoundingBox }, // + FLUSHBEFORE when we implement... or not, do we need to? + { GE_CMD_PRIM, FLAG_EXECUTE, 0, &GPUCommon::Execute_Prim }, + { GE_CMD_BEZIER, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPUCommon::Execute_Bezier }, + { GE_CMD_SPLINE, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPUCommon::Execute_Spline }, + + // Changing the vertex type requires us to flush. + { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_VertexType }, + // These two are actually processed in CMD_END. Not sure if FLAG_FLUSHBEFORE matters. { GE_CMD_SIGNAL, FLAG_FLUSHBEFORE }, { GE_CMD_FINISH, FLAG_FLUSHBEFORE }, @@ -121,7 +128,7 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_TEXOFFSETU }, { GE_CMD_TEXOFFSETV }, - // TEXSIZE0 is handled by each backend. + { GE_CMD_TEXSIZE0, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_TexSize0 }, { GE_CMD_TEXSIZE1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, { GE_CMD_TEXSIZE2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, { GE_CMD_TEXSIZE3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, @@ -1368,6 +1375,81 @@ void GPUCommon::Execute_VertexTypeSkinning(u32 op, u32 diff) { gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE); } + +void GPUCommon::Execute_Prim(u32 op, u32 diff) { + // This drives all drawing. All other state we just buffer up, then we apply it only + // when it's time to draw. As most PSP games set state redundantly ALL THE TIME, this is a huge optimization. + + PROFILE_THIS_SCOPE("execprim"); + + u32 data = op & 0xFFFFFF; + u32 count = data & 0xFFFF; + if (count == 0) + return; + + // Upper bits are ignored. + GEPrimitiveType prim = static_cast((data >> 16) & 7); + SetDrawType(DRAW_PRIM, prim); + + // Discard AA lines as we can't do anything that makes sense with these anyway. The SW plugin might, though. + if (gstate.isAntiAliasEnabled()) { + // Discard AA lines in DOA + if (prim == GE_PRIM_LINE_STRIP) + return; + // Discard AA lines in Summon Night 5 + if ((prim == GE_PRIM_LINES) && gstate.isSkinningEnabled()) + return; + } + + // This also makes skipping drawing very effective. + framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); + + if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { + drawEngineCommon_->SetupVertexDecoder(gstate.vertType); // Do we still need to do this? + // Rough estimate, not sure what's correct. + cyclesExecuted += EstimatePerVertexCost() * count; + return; + } + + if (!Memory::IsValidAddress(gstate_c.vertexAddr)) { + ERROR_LOG_REPORT(G3D, "Bad vertex address %08x!", gstate_c.vertexAddr); + return; + } + + void *verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); + void *inds = 0; + u32 vertexType = gstate.vertType; + if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { + u32 indexAddr = gstate_c.indexAddr; + if (!Memory::IsValidAddress(indexAddr)) { + ERROR_LOG_REPORT(G3D, "Bad index address %08x!", indexAddr); + return; + } + inds = Memory::GetPointerUnchecked(indexAddr); + } + +#ifndef MOBILE_DEVICE + if (prim > GE_PRIM_RECTANGLES) { + ERROR_LOG_REPORT_ONCE(reportPrim, G3D, "Unexpected prim type: %d", prim); + } +#endif + + if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) { + vertexCost_ = EstimatePerVertexCost(); + } + gpuStats.vertexGPUCycles += vertexCost_ * count; + cyclesExecuted += vertexCost_* count; + + int bytesRead = 0; + UpdateUVScaleOffset(); + drawEngineCommon_->SubmitPrim(verts, inds, prim, count, vertexType, &bytesRead); + + // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). + // Some games rely on this, they don't bother reloading VADDR and IADDR. + // The VADDR/IADDR registers are NOT updated. + AdvanceVerts(vertexType, count, bytesRead); +} + void GPUCommon::Execute_Bezier(u32 op, u32 diff) { drawEngineCommon_->DispatchFlush(); diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 1890166ce8..38d28d8e41 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -129,6 +129,7 @@ public: void Execute_VertexType(u32 op, u32 diff); void Execute_VertexTypeSkinning(u32 op, u32 diff); + void Execute_Prim(u32 op, u32 diff); void Execute_Bezier(u32 op, u32 diff); void Execute_Spline(u32 op, u32 diff); void Execute_BoundingBox(u32 op, u32 diff); @@ -316,6 +317,8 @@ protected: DrawType lastDraw_; GEPrimitiveType lastPrim_; + int vertexCost_ = 0; + // No idea how big this buffer needs to be. enum { MAX_IMMBUFFER_SIZE = 32, diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 5bdd2fc086..48314824da 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -57,16 +57,6 @@ GPU_Vulkan::CommandInfo GPU_Vulkan::cmdInfo_[256]; // This table gets crunched into a faster form by init. static const VulkanCommandTableEntry commandTable[] = { - // Changes that dirty the current texture. - { GE_CMD_TEXSIZE0, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_TexSize0 }, - - // Changing the vertex type requires us to flush. - { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_VertexType }, - - { GE_CMD_PRIM, FLAG_EXECUTE, 0, &GPU_Vulkan::Execute_Prim }, - { GE_CMD_BEZIER, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPUCommon::Execute_Bezier }, - { GE_CMD_SPLINE, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPUCommon::Execute_Spline }, - // Changes that trigger data copies. Only flushing on change for LOADCLUT must be a bit of a hack... { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPU_Vulkan::Execute_LoadClut }, }; @@ -520,83 +510,9 @@ void GPU_Vulkan::ExecuteOp(u32 op, u32 diff) { } } -void GPU_Vulkan::Execute_Prim(u32 op, u32 diff) { - // This drives all drawing. All other state we just buffer up, then we apply it only - // when it's time to draw. As most PSP games set state redundantly ALL THE TIME, this is a huge optimization. - - PROFILE_THIS_SCOPE("execprim"); - - u32 data = op & 0xFFFFFF; - u32 count = data & 0xFFFF; - if (count == 0) - return; - - // Upper bits are ignored. - GEPrimitiveType prim = static_cast((data >> 16) & 7); - SetDrawType(DRAW_PRIM, prim); - - // Discard AA lines as we can't do anything that makes sense with these anyway. The SW plugin might, though. - if (gstate.isAntiAliasEnabled()) { - // Discard AA lines in DOA - if (prim == GE_PRIM_LINE_STRIP) - return; - // Discard AA lines in Summon Night 5 - if ((prim == GE_PRIM_LINES) && gstate.isSkinningEnabled()) - return; - } - - // This also makes skipping drawing very effective. - framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); - - if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { - drawEngine_.SetupVertexDecoder(gstate.vertType); // Do we still need to do this? - // Rough estimate, not sure what's correct. - cyclesExecuted += EstimatePerVertexCost() * count; - return; - } - - if (!Memory::IsValidAddress(gstate_c.vertexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad vertex address %08x!", gstate_c.vertexAddr); - return; - } - - void *verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); - void *inds = 0; - u32 vertexType = gstate.vertType; - if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { - u32 indexAddr = gstate_c.indexAddr; - if (!Memory::IsValidAddress(indexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad index address %08x!", indexAddr); - return; - } - inds = Memory::GetPointerUnchecked(indexAddr); - } - -#ifndef MOBILE_DEVICE - if (prim > GE_PRIM_RECTANGLES) { - ERROR_LOG_REPORT_ONCE(reportPrim, G3D, "Unexpected prim type: %d", prim); - } -#endif - - if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) { - vertexCost_ = EstimatePerVertexCost(); - } - gpuStats.vertexGPUCycles += vertexCost_ * count; - cyclesExecuted += vertexCost_* count; - - int bytesRead = 0; - UpdateUVScaleOffset(); - drawEngine_.SubmitPrim(verts, inds, prim, count, vertexType, &bytesRead); - - // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). - // Some games rely on this, they don't bother reloading VADDR and IADDR. - // The VADDR/IADDR registers are NOT updated. - AdvanceVerts(vertexType, count, bytesRead); -} - void GPU_Vulkan::Execute_LoadClut(u32 op, u32 diff) { gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - textureCacheVulkan_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); + textureCache_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); } void GPU_Vulkan::InitDeviceObjects() { diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 63813331fb..9c846dd15d 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -68,7 +68,6 @@ public: GPU_Vulkan::CmdFunc func; }; - void Execute_Prim(u32 op, u32 diff); void Execute_LoadClut(u32 op, u32 diff); // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. @@ -112,8 +111,6 @@ private: // Manages state and pipeline objects PipelineManagerVulkan *pipelineManager_; - int vertexCost_ = 0; - std::string reportingPrimaryInfo_; std::string reportingFullInfo_; From 967018b7f8132c252796294187a214ae4e19caab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 11:26:52 +0100 Subject: [PATCH 184/291] Unify Execute_LoadClut --- GPU/Common/DrawEngineCommon.h | 4 +++- GPU/D3D11/GPU_D3D11.cpp | 33 --------------------------------- GPU/D3D11/GPU_D3D11.h | 2 -- GPU/Directx9/GPU_DX9.cpp | 26 -------------------------- GPU/Directx9/GPU_DX9.h | 2 -- GPU/GLES/GPU_GLES.cpp | 32 -------------------------------- GPU/GLES/GPU_GLES.h | 3 --- GPU/GPUCommon.cpp | 7 +++++++ GPU/GPUCommon.h | 2 ++ GPU/Vulkan/GPU_Vulkan.cpp | 32 -------------------------------- GPU/Vulkan/GPU_Vulkan.h | 2 -- 11 files changed, 12 insertions(+), 133 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 25eb441b06..d2150e4f0c 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -56,7 +56,9 @@ public: // Flush is normally non-virtual but here's a virtual way to call it, used by the shared spline code, which is expensive anyway. // Not really sure if these wrappers are worth it... virtual void DispatchFlush() = 0; - // Same for SubmitPrim + + // This would seem to be unnecessary now, but is still required for splines/beziers to work in the software backend since SubmitPrim + // is different. Should probably refactor that. virtual void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) = 0; bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType, int *bytesRead); diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index e11a6dec2d..4c8a3d591e 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -66,19 +66,6 @@ #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/sceGe.h" -struct D3D11CommandTableEntry { - uint8_t cmd; - uint8_t flags; - uint64_t dirty; - GPU_D3D11::CmdFunc func; -}; - -// This table gets crunched into a faster form by init. -static const D3D11CommandTableEntry commandTable[] = { - // Changes that trigger data copies. Only flushing on change for LOADCLUT must be a bit of a hack... - { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPU_D3D11::Execute_LoadClut }, -}; - GPU_D3D11::CommandInfo GPU_D3D11::cmdInfo_[256]{}; GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) @@ -134,20 +121,6 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) } } - for (size_t i = 0; i < ARRAY_SIZE(commandTable); i++) { - const u8 cmd = commandTable[i].cmd; - if (dupeCheck.find(cmd) != dupeCheck.end()) { - ERROR_LOG(G3D, "Command table Dupe: %02x (%i)", (int)cmd, (int)cmd); - } else { - dupeCheck.insert(cmd); - } - cmdInfo_[cmd].flags |= (uint64_t)commandTable[i].flags | (commandTable[i].dirty << 8); - cmdInfo_[cmd].func = commandTable[i].func; - if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { - Crash(); - } - } - // Find commands missing from the table. for (int i = 0; i < 0xEF; i++) { if (dupeCheck.find((u8)i) == dupeCheck.end()) { @@ -425,12 +398,6 @@ void GPU_D3D11::ExecuteOp(u32 op, u32 diff) { } } -void GPU_D3D11::Execute_LoadClut(u32 op, u32 diff) { - gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - textureCache_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); - // This could be used to "dirty" textures with clut. -} - void GPU_D3D11::GetStats(char *buffer, size_t bufsize) { float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f; snprintf(buffer, bufsize - 1, diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 0719144feb..470837af44 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -64,8 +64,6 @@ public: GPU_D3D11::CmdFunc func; }; - void Execute_LoadClut(u32 op, u32 diff); - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 04b2f0ddda..3704269b25 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -50,19 +50,6 @@ namespace DX9 { -struct D3D9CommandTableEntry { - uint8_t cmd; - uint8_t flags; - uint64_t dirty; - GPU_DX9::CmdFunc func; -}; - -// This table gets crunched into a faster form by init. -static const D3D9CommandTableEntry commandTable[] = { - // Changes that trigger data copies. Only flushing on change for LOADCLUT must be a bit of a hack... - { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPU_DX9::Execute_LoadClut }, -}; - GPU_DX9::CommandInfo GPU_DX9::cmdInfo_[256]; GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) @@ -116,19 +103,6 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) } } - for (size_t i = 0; i < ARRAY_SIZE(commandTable); i++) { - const u8 cmd = commandTable[i].cmd; - if (dupeCheck.find(cmd) != dupeCheck.end()) { - ERROR_LOG(G3D, "Command table Dupe: %02x (%i)", (int)cmd, (int)cmd); - } else { - dupeCheck.insert(cmd); - } - cmdInfo_[cmd].flags |= (uint64_t)commandTable[i].flags | (commandTable[i].dirty << 8); - cmdInfo_[cmd].func = commandTable[i].func; - if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { - Crash(); - } - } // Find commands missing from the table. for (int i = 0; i < 0xEF; i++) { if (dupeCheck.find((u8)i) == dupeCheck.end()) { diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 30f661696f..5edae1e5a9 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -65,8 +65,6 @@ public: GPU_DX9::CmdFunc func; }; - void Execute_LoadClut(u32 op, u32 diff); - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 8ec5f19103..ea6c6a17ec 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -51,20 +51,6 @@ #include "Windows/GPU/WindowsGLContext.h" #endif -struct GLESCommandTableEntry { - uint8_t cmd; - uint8_t flags; - uint64_t dirty; - GPU_GLES::CmdFunc func; -}; - -// This table gets crunched into a faster form by init. -// TODO: Share this table between the backends. Will have to make another indirection for the function pointers though.. -static const GLESCommandTableEntry commandTable[] = { - // Changes that trigger data copies. Only flushing on change for LOADCLUT must be a bit of a hack... - { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPU_GLES::Execute_LoadClut }, -}; - GPU_GLES::CommandInfo GPU_GLES::cmdInfo_[256]; GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) @@ -120,19 +106,6 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) } } - for (size_t i = 0; i < ARRAY_SIZE(commandTable); i++) { - const u8 cmd = commandTable[i].cmd; - if (dupeCheck.find(cmd) != dupeCheck.end()) { - ERROR_LOG(G3D, "Command table Dupe: %02x (%i)", (int)cmd, (int)cmd); - } else { - dupeCheck.insert(cmd); - } - cmdInfo_[cmd].flags |= (uint64_t)commandTable[i].flags | (commandTable[i].dirty << 8); - cmdInfo_[cmd].func = commandTable[i].func; - if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { - Crash(); - } - } // Find commands missing from the table. for (int i = 0; i < 0xEF; i++) { if (dupeCheck.find((u8)i) == dupeCheck.end()) { @@ -615,11 +588,6 @@ void GPU_GLES::ExecuteOp(u32 op, u32 diff) { } } -void GPU_GLES::Execute_LoadClut(u32 op, u32 diff) { - gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - textureCache_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); -} - void GPU_GLES::GetStats(char *buffer, size_t bufsize) { float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f; snprintf(buffer, bufsize - 1, diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index f23c5ddf9d..3cedc50e8d 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -69,9 +69,6 @@ public: GPU_GLES::CmdFunc func; }; - void Execute_Prim(u32 op, u32 diff); - void Execute_LoadClut(u32 op, u32 diff); - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 16ecf8c23a..f92920ffd3 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -49,6 +49,8 @@ const CommonCommandTableEntry commonCommandTable[] = { // Changing the vertex type requires us to flush. { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_VertexType }, + { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_LoadClut }, + // These two are actually processed in CMD_END. Not sure if FLAG_FLUSHBEFORE matters. { GE_CMD_SIGNAL, FLAG_FLUSHBEFORE }, { GE_CMD_FINISH, FLAG_FLUSHBEFORE }, @@ -1354,6 +1356,11 @@ void GPUCommon::Execute_VertexType(u32 op, u32 diff) { } } +void GPUCommon::Execute_LoadClut(u32 op, u32 diff) { + gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); + textureCache_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); +} + void GPUCommon::Execute_VertexTypeSkinning(u32 op, u32 diff) { // Don't flush when weight count changes, unless morph is enabled. if ((diff & ~GE_VTYPE_WEIGHTCOUNT_MASK) || (op & GE_VTYPE_MORPHCOUNT_MASK) != 0) { diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 38d28d8e41..f60dec18cd 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -135,6 +135,8 @@ public: void Execute_BoundingBox(u32 op, u32 diff); void Execute_BlockTransferStart(u32 op, u32 diff); + void Execute_LoadClut(u32 op, u32 diff); + void Execute_TexSize0(u32 op, u32 diff); void Execute_TexLevel(u32 op, u32 diff); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 48314824da..4e05af6bc6 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -46,21 +46,8 @@ #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/sceGe.h" -struct VulkanCommandTableEntry { - uint8_t cmd; - uint8_t flags; - uint64_t dirty; - GPU_Vulkan::CmdFunc func; -}; - GPU_Vulkan::CommandInfo GPU_Vulkan::cmdInfo_[256]; -// This table gets crunched into a faster form by init. -static const VulkanCommandTableEntry commandTable[] = { - // Changes that trigger data copies. Only flushing on change for LOADCLUT must be a bit of a hack... - { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPU_Vulkan::Execute_LoadClut }, -}; - GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw), vulkan_((VulkanContext *)gfxCtx->GetAPIContext()), @@ -118,20 +105,6 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) Crash(); } } - - for (size_t i = 0; i < ARRAY_SIZE(commandTable); i++) { - const u8 cmd = commandTable[i].cmd; - if (dupeCheck.find(cmd) != dupeCheck.end()) { - ERROR_LOG(G3D, "Command table Dupe: %02x (%i)", (int)cmd, (int)cmd); - } else { - dupeCheck.insert(cmd); - } - cmdInfo_[cmd].flags |= (uint64_t)commandTable[i].flags | (commandTable[i].dirty << 8); - cmdInfo_[cmd].func = commandTable[i].func; - if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { - Crash(); - } - } // Find commands missing from the table. for (int i = 0; i < 0xEF; i++) { if (dupeCheck.find((u8)i) == dupeCheck.end()) { @@ -510,11 +483,6 @@ void GPU_Vulkan::ExecuteOp(u32 op, u32 diff) { } } -void GPU_Vulkan::Execute_LoadClut(u32 op, u32 diff) { - gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - textureCache_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); -} - void GPU_Vulkan::InitDeviceObjects() { ILOG("GPU_Vulkan::InitDeviceObjects"); // Initialize framedata diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 9c846dd15d..1a081b0514 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -67,8 +67,6 @@ public: uint64_t flags; GPU_Vulkan::CmdFunc func; }; - - void Execute_LoadClut(u32 op, u32 diff); // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; From feb4694accdb7fd3f783c850e66d78e213efa25c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 11:33:17 +0100 Subject: [PATCH 185/291] Unify DispatchSubmitPrim as much as possible --- GPU/Common/DrawEngineCommon.h | 4 +++- GPU/D3D11/DrawEngineD3D11.h | 3 --- GPU/Directx9/DrawEngineDX9.h | 3 --- GPU/GLES/DrawEngineGLES.h | 3 --- GPU/Vulkan/DrawEngineVulkan.h | 3 --- 5 files changed, 3 insertions(+), 13 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index d2150e4f0c..10af8ca780 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -59,7 +59,9 @@ public: // This would seem to be unnecessary now, but is still required for splines/beziers to work in the software backend since SubmitPrim // is different. Should probably refactor that. - virtual void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) = 0; + virtual void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) { + SubmitPrim(verts, inds, prim, vertexCount, vertType, bytesRead); + } bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType, int *bytesRead); diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index 3a88d7ae97..9d4589baae 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -133,9 +133,6 @@ public: } void DispatchFlush() override { Flush(); } - void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) override { - SubmitPrim(verts, inds, prim, vertexCount, vertType, bytesRead); - } void ClearTrackedVertexArrays() override; diff --git a/GPU/Directx9/DrawEngineDX9.h b/GPU/Directx9/DrawEngineDX9.h index 171675f3e0..ef015b02b5 100644 --- a/GPU/Directx9/DrawEngineDX9.h +++ b/GPU/Directx9/DrawEngineDX9.h @@ -132,9 +132,6 @@ public: } void DispatchFlush() override { Flush(); } - void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) override { - SubmitPrim(verts, inds, prim, vertexCount, vertType, bytesRead); - } private: void DoFlush(); diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 62340af75c..42e4ce5133 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -144,9 +144,6 @@ public: bool IsCodePtrVertexDecoder(const u8 *ptr) const; void DispatchFlush() override { Flush(); } - void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) override { - SubmitPrim(verts, inds, prim, vertexCount, vertType, bytesRead); - } GLPushBuffer *GetPushVertexBuffer() { return frameData_[render_->GetCurFrame()].pushVertex; diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index a80f05a5d9..d39186837c 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -155,9 +155,6 @@ public: } void DispatchFlush() override { Flush(); } - void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) override { - SubmitPrim(verts, inds, prim, vertexCount, vertType, bytesRead); - } VkPipelineLayout GetPipelineLayout() const { return pipelineLayout_; From a8a34fef9c427c2be88580f968177df2086df17e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 11:35:37 +0100 Subject: [PATCH 186/291] Virtualize CheckGPUFeatures --- GPU/D3D11/GPU_D3D11.h | 2 +- GPU/Directx9/GPU_DX9.h | 2 +- GPU/GLES/GPU_GLES.h | 2 +- GPU/GPUCommon.h | 2 ++ GPU/Null/NullGpu.h | 2 ++ GPU/Software/SoftGpu.h | 2 ++ GPU/Vulkan/GPU_Vulkan.h | 2 +- 7 files changed, 10 insertions(+), 4 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 470837af44..28eeccb522 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -36,7 +36,7 @@ public: GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw); ~GPU_D3D11(); - void CheckGPUFeatures(); + void CheckGPUFeatures() override; void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 5edae1e5a9..9ea2f95c1e 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -37,7 +37,7 @@ public: GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw); ~GPU_DX9(); - void CheckGPUFeatures(); + void CheckGPUFeatures() override; void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 3cedc50e8d..d6ed19083d 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -36,7 +36,7 @@ public: ~GPU_GLES(); // This gets called on startup and when we get back from settings. - void CheckGPUFeatures(); + void CheckGPUFeatures() override; bool IsReady() override; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index f60dec18cd..b19077e3c0 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -70,6 +70,8 @@ public: Draw::DrawContext *GetDrawContext() override { return draw_; } + virtual void CheckGPUFeatures() = 0; + bool IsReady() override { return true; } diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index 59b920723c..12deca5d41 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -26,6 +26,8 @@ class NullGPU : public GPUCommon { public: NullGPU(); ~NullGPU(); + + void CheckGPUFeatures() override {} void InitClear() override {} void ExecuteOp(u32 op, u32 diff) override; diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 7d5750b043..92762a487f 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -52,6 +52,8 @@ class SoftGPU : public GPUCommon { public: SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *_thin3D); ~SoftGPU(); + + void CheckGPUFeatures() override {} void InitClear() override {} void ExecuteOp(u32 op, u32 diff) override; diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 1a081b0514..81f213bb18 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -36,7 +36,7 @@ public: ~GPU_Vulkan(); // This gets called on startup and when we get back from settings. - void CheckGPUFeatures(); + void CheckGPUFeatures() override; // These are where we can reset command buffers etc. void BeginHostFrame() override; From 8cef1f0f8dab4cb3f8f629c271a1cb27ff8a0fc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 11:44:02 +0100 Subject: [PATCH 187/291] GPU: Unify command table (cmdInfo_) --- GPU/D3D11/GPU_D3D11.cpp | 27 --------------------------- GPU/D3D11/GPU_D3D11.h | 8 -------- GPU/Directx9/GPU_DX9.cpp | 27 --------------------------- GPU/Directx9/GPU_DX9.h | 8 -------- GPU/GLES/GPU_GLES.cpp | 27 --------------------------- GPU/GLES/GPU_GLES.h | 8 -------- GPU/GPUCommon.cpp | 27 +++++++++++++++++++++++++++ GPU/GPUCommon.h | 8 ++++++++ GPU/Vulkan/GPU_Vulkan.cpp | 26 -------------------------- GPU/Vulkan/GPU_Vulkan.h | 8 -------- 10 files changed, 35 insertions(+), 139 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 4c8a3d591e..eabd5d3507 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -66,8 +66,6 @@ #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/sceGe.h" -GPU_D3D11::CommandInfo GPU_D3D11::cmdInfo_[256]{}; - GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw), drawEngine_(draw, (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE), @@ -103,31 +101,6 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) ERROR_LOG(G3D, "gstate has drifted out of sync!"); } - memset(cmdInfo_, 0, sizeof(cmdInfo_)); - - // Import both the global and local command tables, and check for dupes - std::set dupeCheck; - for (size_t i = 0; i < commonCommandTableSize; i++) { - const u8 cmd = commonCommandTable[i].cmd; - if (dupeCheck.find(cmd) != dupeCheck.end()) { - ERROR_LOG(G3D, "Command table Dupe: %02x (%i)", (int)cmd, (int)cmd); - } else { - dupeCheck.insert(cmd); - } - cmdInfo_[cmd].flags |= (uint64_t)commonCommandTable[i].flags | (commonCommandTable[i].dirty << 8); - cmdInfo_[cmd].func = commonCommandTable[i].func; - if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { - Crash(); - } - } - - // Find commands missing from the table. - for (int i = 0; i < 0xEF; i++) { - if (dupeCheck.find((u8)i) == dupeCheck.end()) { - ERROR_LOG(G3D, "Command missing from table: %02x (%i)", i, i); - } - } - // No need to flush before the tex scale/offset commands if we are baking // the tex scale/offset into the vertices anyway. UpdateCmdInfo(); diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 28eeccb522..c9cb6bad2f 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -58,12 +58,6 @@ public: fullInfo = reportingFullInfo_; } - typedef void (GPU_D3D11::*CmdFunc)(u32 op, u32 diff); - struct CommandInfo { - uint64_t flags; - GPU_D3D11::CmdFunc func; - }; - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; @@ -98,8 +92,6 @@ private: DrawEngineD3D11 drawEngine_; ShaderManagerD3D11 *shaderManagerD3D11_; - static CommandInfo cmdInfo_[256]; - int lastVsync_; int vertexCost_ = 0; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 3704269b25..504ab226c1 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -50,8 +50,6 @@ namespace DX9 { -GPU_DX9::CommandInfo GPU_DX9::cmdInfo_[256]; - GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw), depalShaderCache_(draw), @@ -85,31 +83,6 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) ERROR_LOG(G3D, "gstate has drifted out of sync!"); } - memset(cmdInfo_, 0, sizeof(cmdInfo_)); - - // Import both the global and local command tables, and check for dupes - std::set dupeCheck; - for (size_t i = 0; i < commonCommandTableSize; i++) { - const u8 cmd = commonCommandTable[i].cmd; - if (dupeCheck.find(cmd) != dupeCheck.end()) { - ERROR_LOG(G3D, "Command table Dupe: %02x (%i)", (int)cmd, (int)cmd); - } else { - dupeCheck.insert(cmd); - } - cmdInfo_[cmd].flags |= (uint64_t)commonCommandTable[i].flags | (commonCommandTable[i].dirty << 8); - cmdInfo_[cmd].func = commonCommandTable[i].func; - if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { - Crash(); - } - } - - // Find commands missing from the table. - for (int i = 0; i < 0xEF; i++) { - if (dupeCheck.find((u8)i) == dupeCheck.end()) { - ERROR_LOG(G3D, "Command missing from table: %02x (%i)", i, i); - } - } - // No need to flush before the tex scale/offset commands if we are baking // the tex scale/offset into the vertices anyway. UpdateCmdInfo(); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 9ea2f95c1e..9a168628f3 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -59,12 +59,6 @@ public: fullInfo = reportingFullInfo_; } - typedef void (GPU_DX9::*CmdFunc)(u32 op, u32 diff); - struct CommandInfo { - uint64_t flags; - GPU_DX9::CmdFunc func; - }; - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; @@ -98,8 +92,6 @@ private: DrawEngineDX9 drawEngine_; ShaderManagerDX9 *shaderManagerDX9_; - static CommandInfo cmdInfo_[256]; - int lastVsync_; int vertexCost_ = 0; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index ea6c6a17ec..b73caca731 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -51,8 +51,6 @@ #include "Windows/GPU/WindowsGLContext.h" #endif -GPU_GLES::CommandInfo GPU_GLES::cmdInfo_[256]; - GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw), drawEngine_(draw), fragmentTestCache_(draw), depalShaderCache_(draw) { UpdateVsyncInterval(true); @@ -88,31 +86,6 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) ERROR_LOG(G3D, "gstate has drifted out of sync!"); } - memset(cmdInfo_, 0, sizeof(cmdInfo_)); - - // Import both the global and local command tables, and check for dupes - std::set dupeCheck; - for (size_t i = 0; i < commonCommandTableSize; i++) { - const u8 cmd = commonCommandTable[i].cmd; - if (dupeCheck.find(cmd) != dupeCheck.end()) { - ERROR_LOG(G3D, "Command table Dupe: %02x (%i)", (int)cmd, (int)cmd); - } else { - dupeCheck.insert(cmd); - } - cmdInfo_[cmd].flags |= (uint64_t)commonCommandTable[i].flags | (commonCommandTable[i].dirty << 8); - cmdInfo_[cmd].func = commonCommandTable[i].func; - if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { - Crash(); - } - } - - // Find commands missing from the table. - for (int i = 0; i < 0xEF; i++) { - if (dupeCheck.find((u8)i) == dupeCheck.end()) { - ERROR_LOG(G3D, "Command missing from table: %02x (%i)", i, i); - } - } - // No need to flush before the tex scale/offset commands if we are baking // the tex scale/offset into the vertices anyway. diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index d6ed19083d..0184ab604d 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -63,12 +63,6 @@ public: fullInfo = reportingFullInfo_; } - typedef void (GPU_GLES::*CmdFunc)(u32 op, u32 diff); - struct CommandInfo { - uint64_t flags; - GPU_GLES::CmdFunc func; - }; - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; @@ -95,8 +89,6 @@ private: inline void UpdateVsyncInterval(bool force); void UpdateCmdInfo(); - static CommandInfo cmdInfo_[256]; - FramebufferManagerGLES *framebufferManagerGL_; TextureCacheGLES *textureCacheGL_; DepalShaderCacheGLES depalShaderCache_; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index f92920ffd3..e63411c5b0 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -352,6 +352,9 @@ const CommonCommandTableEntry commonCommandTable[] = { }; size_t commonCommandTableSize = ARRAY_SIZE(commonCommandTable); +// TODO: Make class member? +GPUCommon::CommandInfo GPUCommon::cmdInfo_[256]; + void GPUCommon::Flush() { drawEngineCommon_->DispatchFlush(); } @@ -375,6 +378,30 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : gstate.Reset(); gstate_c.Reset(); gpuStats.Reset(); + + memset(cmdInfo_, 0, sizeof(cmdInfo_)); + + // Import both the global and local command tables, and check for dupes + std::set dupeCheck; + for (size_t i = 0; i < commonCommandTableSize; i++) { + const u8 cmd = commonCommandTable[i].cmd; + if (dupeCheck.find(cmd) != dupeCheck.end()) { + ERROR_LOG(G3D, "Command table Dupe: %02x (%i)", (int)cmd, (int)cmd); + } else { + dupeCheck.insert(cmd); + } + cmdInfo_[cmd].flags |= (uint64_t)commonCommandTable[i].flags | (commonCommandTable[i].dirty << 8); + cmdInfo_[cmd].func = commonCommandTable[i].func; + if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { + Crash(); + } + } + // Find commands missing from the table. + for (int i = 0; i < 0xEF; i++) { + if (dupeCheck.find((u8)i) == dupeCheck.end()) { + ERROR_LOG(G3D, "Command missing from table: %02x (%i)", i, i); + } + } } GPUCommon::~GPUCommon() { diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index b19077e3c0..f203660216 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -295,6 +295,14 @@ protected: GraphicsContext *gfxCtx_; Draw::DrawContext *draw_; + typedef void (GPUCommon::*CmdFunc)(u32 op, u32 diff); + struct CommandInfo { + uint64_t flags; + GPUCommon::CmdFunc func; + }; + + static CommandInfo cmdInfo_[256]; + typedef std::list DisplayListQueue; int nextListID; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 4e05af6bc6..8f7dd68c1c 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -46,8 +46,6 @@ #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/sceGe.h" -GPU_Vulkan::CommandInfo GPU_Vulkan::cmdInfo_[256]; - GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw), vulkan_((VulkanContext *)gfxCtx->GetAPIContext()), @@ -88,30 +86,6 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) ERROR_LOG(G3D, "gstate has drifted out of sync!"); } - memset(cmdInfo_, 0, sizeof(cmdInfo_)); - - // Import both the global and local command tables, and check for dupes - std::set dupeCheck; - for (size_t i = 0; i < commonCommandTableSize; i++) { - const u8 cmd = commonCommandTable[i].cmd; - if (dupeCheck.find(cmd) != dupeCheck.end()) { - ERROR_LOG(G3D, "Command table Dupe: %02x (%i)", (int)cmd, (int)cmd); - } else { - dupeCheck.insert(cmd); - } - cmdInfo_[cmd].flags |= (uint64_t)commonCommandTable[i].flags | (commonCommandTable[i].dirty << 8); - cmdInfo_[cmd].func = commonCommandTable[i].func; - if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { - Crash(); - } - } - // Find commands missing from the table. - for (int i = 0; i < 0xEF; i++) { - if (dupeCheck.find((u8)i) == dupeCheck.end()) { - ERROR_LOG(G3D, "Command missing from table: %02x (%i)", i, i); - } - } - UpdateCmdInfo(); BuildReportingInfo(); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 81f213bb18..162e9a0992 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -62,12 +62,6 @@ public: fullInfo = reportingFullInfo_; } - typedef void (GPU_Vulkan::*CmdFunc)(u32 op, u32 diff); - struct CommandInfo { - uint64_t flags; - GPU_Vulkan::CmdFunc func; - }; - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; @@ -95,8 +89,6 @@ private: void InitDeviceObjects(); void DestroyDeviceObjects(); - static CommandInfo cmdInfo_[256]; - VulkanContext *vulkan_; FramebufferManagerVulkan *framebufferManagerVulkan_; TextureCacheVulkan *textureCacheVulkan_; From 6a2f45c2e123d616feb6e2636baebb7898735f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 11:48:56 +0100 Subject: [PATCH 188/291] Unify UpdateCmdInfo --- GPU/D3D11/GPU_D3D11.cpp | 12 ------------ GPU/D3D11/GPU_D3D11.h | 2 -- GPU/Directx9/GPU_DX9.cpp | 12 ------------ GPU/Directx9/GPU_DX9.h | 2 -- GPU/GLES/GPU_GLES.cpp | 10 ---------- GPU/GLES/GPU_GLES.h | 1 - GPU/GPUCommon.cpp | 12 ++++++++++++ GPU/GPUCommon.h | 2 ++ GPU/Vulkan/GPU_Vulkan.cpp | 12 ------------ GPU/Vulkan/GPU_Vulkan.h | 1 - 10 files changed, 14 insertions(+), 52 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index eabd5d3507..e14b1b1499 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -123,18 +123,6 @@ GPU_D3D11::~GPU_D3D11() { stockD3D11.Destroy(); } -void GPU_D3D11::UpdateCmdInfo() { - if (g_Config.bSoftwareSkinning) { - cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexTypeSkinning; - } else { - cmdInfo_[GE_CMD_VERTEXTYPE].flags |= FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexType; - } - - CheckGPUFeatures(); -} - void GPU_D3D11::CheckGPUFeatures() { u32 features = 0; diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index c9cb6bad2f..23d5582759 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -70,8 +70,6 @@ protected: void FinishDeferred() override; private: - void UpdateCmdInfo(); - void Flush() { drawEngine_.Flush(); } diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 504ab226c1..173f7dc004 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -103,18 +103,6 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) } } -void GPU_DX9::UpdateCmdInfo() { - if (g_Config.bSoftwareSkinning) { - cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexTypeSkinning; - } else { - cmdInfo_[GE_CMD_VERTEXTYPE].flags |= FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexType; - } - - CheckGPUFeatures(); -} - void GPU_DX9::CheckGPUFeatures() { u32 features = 0; diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 9a168628f3..45cc632c63 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -70,8 +70,6 @@ protected: void FinishDeferred() override; private: - void UpdateCmdInfo(); - void Flush() { drawEngine_.Flush(); } diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index b73caca731..d0290c5e5f 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -407,16 +407,6 @@ inline void GPU_GLES::UpdateVsyncInterval(bool force) { #endif } -void GPU_GLES::UpdateCmdInfo() { - if (g_Config.bSoftwareSkinning) { - cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexTypeSkinning; - } else { - cmdInfo_[GE_CMD_VERTEXTYPE].flags |= FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexType; - } -} - void GPU_GLES::ReapplyGfxState() { GPUCommon::ReapplyGfxState(); } diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 0184ab604d..9c3a4ada43 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -87,7 +87,6 @@ private: void Reinitialize() override; inline void UpdateVsyncInterval(bool force); - void UpdateCmdInfo(); FramebufferManagerGLES *framebufferManagerGL_; TextureCacheGLES *textureCacheGL_; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index e63411c5b0..cbf22a9c28 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -402,11 +402,23 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : ERROR_LOG(G3D, "Command missing from table: %02x (%i)", i, i); } } + + UpdateCmdInfo(); } GPUCommon::~GPUCommon() { } +void GPUCommon::UpdateCmdInfo() { + if (g_Config.bSoftwareSkinning) { + cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE; + cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexTypeSkinning; + } else { + cmdInfo_[GE_CMD_VERTEXTYPE].flags |= FLAG_FLUSHBEFOREONCHANGE; + cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexType; + } +} + void GPUCommon::BeginHostFrame() { ReapplyGfxState(); diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index f203660216..2c99e2aaaf 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -72,6 +72,8 @@ public: } virtual void CheckGPUFeatures() = 0; + void UpdateCmdInfo(); + bool IsReady() override { return true; } diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 8f7dd68c1c..1f8fa0bc57 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -86,8 +86,6 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) ERROR_LOG(G3D, "gstate has drifted out of sync!"); } - UpdateCmdInfo(); - BuildReportingInfo(); // Update again after init to be sure of any silly driver problems. UpdateVsyncInterval(true); @@ -342,16 +340,6 @@ void GPU_Vulkan::UpdateVsyncInterval(bool force) { // TODO } -void GPU_Vulkan::UpdateCmdInfo() { - if (g_Config.bSoftwareSkinning) { - cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexTypeSkinning; - } else { - cmdInfo_[GE_CMD_VERTEXTYPE].flags |= FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexType; - } -} - void GPU_Vulkan::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) { host->GPUNotifyDisplay(framebuf, stride, format); framebufferManager_->SetDisplayFramebuffer(framebuf, stride, format); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 162e9a0992..2bb8b3cf26 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -84,7 +84,6 @@ private: void CopyDisplayToOutput() override; void Reinitialize() override; inline void UpdateVsyncInterval(bool force); - void UpdateCmdInfo(); void InitDeviceObjects(); void DestroyDeviceObjects(); From 78467d6092e0caf89bafa52674d390b41701d281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 11:52:16 +0100 Subject: [PATCH 189/291] Unify FastRunLoop for the hardware backends. --- GPU/D3D11/GPU_D3D11.cpp | 38 -------------------------------------- GPU/D3D11/GPU_D3D11.h | 1 - GPU/Directx9/GPU_DX9.cpp | 38 -------------------------------------- GPU/Directx9/GPU_DX9.h | 1 - GPU/GLES/GPU_GLES.cpp | 38 -------------------------------------- GPU/GLES/GPU_GLES.h | 1 - GPU/GPUCommon.cpp | 38 ++++++++++++++++++++++++++++++++++++++ GPU/GPUCommon.h | 4 ++-- GPU/Vulkan/GPU_Vulkan.cpp | 38 -------------------------------------- GPU/Vulkan/GPU_Vulkan.h | 1 - 10 files changed, 40 insertions(+), 158 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index e14b1b1499..5dbe449087 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -289,44 +289,6 @@ void GPU_D3D11::CopyDisplayToOutput() { gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); } -// Maybe should write this in ASM... -void GPU_D3D11::FastRunLoop(DisplayList &list) { - PROFILE_THIS_SCOPE("gpuloop"); - const CommandInfo *cmdInfo = cmdInfo_; - int dc = downcount; - for (; dc > 0; --dc) { - // We know that display list PCs have the upper nibble == 0 - no need to mask the pointer - const u32 op = *(const u32 *)(Memory::base + list.pc); - const u32 cmd = op >> 24; - const CommandInfo &info = cmdInfo[cmd]; - const u32 diff = op ^ gstate.cmdmem[cmd]; - if (diff == 0) { - if (info.flags & FLAG_EXECUTE) { - downcount = dc; - (this->*info.func)(op, diff); - dc = downcount; - } - } else { - uint64_t flags = info.flags; - if (flags & FLAG_FLUSHBEFOREONCHANGE) { - drawEngine_.Flush(); - } - gstate.cmdmem[cmd] = op; - if (flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) { - downcount = dc; - (this->*info.func)(op, diff); - dc = downcount; - } else { - uint64_t dirty = flags >> 8; - if (dirty) - gstate_c.Dirty(dirty); - } - } - list.pc += 4; - } - downcount = 0; -} - void GPU_D3D11::FinishDeferred() { // This finishes reading any vertex data that is pending. drawEngine_.FinishDeferred(); diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 23d5582759..aadaef4556 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -66,7 +66,6 @@ public: void EndHostFrame() override; protected: - void FastRunLoop(DisplayList &list) override; void FinishDeferred() override; private: diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 173f7dc004..32c03fd030 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -265,44 +265,6 @@ void GPU_DX9::CopyDisplayToOutput() { gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); } -// Maybe should write this in ASM... -void GPU_DX9::FastRunLoop(DisplayList &list) { - PROFILE_THIS_SCOPE("gpuloop"); - const CommandInfo *cmdInfo = cmdInfo_; - int dc = downcount; - for (; dc > 0; --dc) { - // We know that display list PCs have the upper nibble == 0 - no need to mask the pointer - const u32 op = *(const u32 *)(Memory::base + list.pc); - const u32 cmd = op >> 24; - const CommandInfo &info = cmdInfo[cmd]; - const u32 diff = op ^ gstate.cmdmem[cmd]; - if (diff == 0) { - if (info.flags & FLAG_EXECUTE) { - downcount = dc; - (this->*info.func)(op, diff); - dc = downcount; - } - } else { - uint64_t flags = info.flags; - if (flags & FLAG_FLUSHBEFOREONCHANGE) { - drawEngine_.Flush(); - } - gstate.cmdmem[cmd] = op; - if (flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) { - downcount = dc; - (this->*info.func)(op, diff); - dc = downcount; - } else { - uint64_t dirty = flags >> 8; - if (dirty) - gstate_c.Dirty(dirty); - } - } - list.pc += 4; - } - downcount = 0; -} - void GPU_DX9::FinishDeferred() { // This finishes reading any vertex data that is pending. drawEngine_.FinishDeferred(); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 45cc632c63..2681bd4c79 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -66,7 +66,6 @@ public: void BeginHostFrame() override; protected: - void FastRunLoop(DisplayList &list) override; void FinishDeferred() override; private: diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index d0290c5e5f..44962d935a 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -481,44 +481,6 @@ void GPU_GLES::CopyDisplayToOutput() { #endif } -// Maybe should write this in ASM... -void GPU_GLES::FastRunLoop(DisplayList &list) { - PROFILE_THIS_SCOPE("gpuloop"); - const CommandInfo *cmdInfo = cmdInfo_; - int dc = downcount; - for (; dc > 0; --dc) { - // We know that display list PCs have the upper nibble == 0 - no need to mask the pointer - const u32 op = *(const u32 *)(Memory::base + list.pc); - const u32 cmd = op >> 24; - const CommandInfo &info = cmdInfo[cmd]; - const u32 diff = op ^ gstate.cmdmem[cmd]; - if (diff == 0) { - if (info.flags & FLAG_EXECUTE) { - downcount = dc; - (this->*info.func)(op, diff); - dc = downcount; - } - } else { - uint64_t flags = info.flags; - if (flags & FLAG_FLUSHBEFOREONCHANGE) { - drawEngine_.Flush(); - } - gstate.cmdmem[cmd] = op; - if (flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) { - downcount = dc; - (this->*info.func)(op, diff); - dc = downcount; - } else { - uint64_t dirty = flags >> 8; - if (dirty) - gstate_c.Dirty(dirty); - } - } - list.pc += 4; - } - downcount = 0; -} - void GPU_GLES::FinishDeferred() { // This finishes reading any vertex data that is pending. drawEngine_.FinishDeferred(); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 9c3a4ada43..b81f349dd5 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -71,7 +71,6 @@ public: void EndHostFrame() override; protected: - void FastRunLoop(DisplayList &list) override; void FinishDeferred() override; private: diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index cbf22a9c28..fc9bf6b62a 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -965,6 +965,44 @@ bool GPUCommon::InterpretList(DisplayList &list) { return gpuState == GPUSTATE_DONE || gpuState == GPUSTATE_ERROR; } +// Maybe should write this in ASM... +void GPUCommon::FastRunLoop(DisplayList &list) { + PROFILE_THIS_SCOPE("gpuloop"); + const CommandInfo *cmdInfo = cmdInfo_; + int dc = downcount; + for (; dc > 0; --dc) { + // We know that display list PCs have the upper nibble == 0 - no need to mask the pointer + const u32 op = *(const u32 *)(Memory::base + list.pc); + const u32 cmd = op >> 24; + const CommandInfo &info = cmdInfo[cmd]; + const u32 diff = op ^ gstate.cmdmem[cmd]; + if (diff == 0) { + if (info.flags & FLAG_EXECUTE) { + downcount = dc; + (this->*info.func)(op, diff); + dc = downcount; + } + } else { + uint64_t flags = info.flags; + if (flags & FLAG_FLUSHBEFOREONCHANGE) { + drawEngineCommon_->DispatchFlush(); + } + gstate.cmdmem[cmd] = op; + if (flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) { + downcount = dc; + (this->*info.func)(op, diff); + dc = downcount; + } else { + uint64_t dirty = flags >> 8; + if (dirty) + gstate_c.Dirty(dirty); + } + } + list.pc += 4; + } + downcount = 0; +} + void GPUCommon::BeginFrame() { immCount_ = 0; if (dumpNextFrame_) { diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 2c99e2aaaf..e83c499d79 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -265,8 +265,8 @@ protected: void BeginFrame() override; - // To avoid virtual calls to PreExecuteOp(). - virtual void FastRunLoop(DisplayList &list) = 0; + virtual void FastRunLoop(DisplayList &list); + void SlowRunLoop(DisplayList &list); void UpdatePC(u32 currentPC, u32 newPC); void UpdateState(GPURunState state); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 1f8fa0bc57..a95e93d911 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -376,44 +376,6 @@ void GPU_Vulkan::CopyDisplayToOutput() { gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); } -// Maybe should write this in ASM... -void GPU_Vulkan::FastRunLoop(DisplayList &list) { - PROFILE_THIS_SCOPE("gpuloop"); - const CommandInfo *cmdInfo = cmdInfo_; - int dc = downcount; - for (; dc > 0; --dc) { - // We know that display list PCs have the upper nibble == 0 - no need to mask the pointer - const u32 op = *(const u32 *)(Memory::base + list.pc); - const u32 cmd = op >> 24; - const CommandInfo &info = cmdInfo[cmd]; - const u32 diff = op ^ gstate.cmdmem[cmd]; - if (diff == 0) { - if (info.flags & FLAG_EXECUTE) { - downcount = dc; - (this->*info.func)(op, diff); - dc = downcount; - } - } else { - uint64_t flags = info.flags; - if (flags & FLAG_FLUSHBEFOREONCHANGE) { - drawEngine_.Flush(); - } - gstate.cmdmem[cmd] = op; - if (flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) { - downcount = dc; - (this->*info.func)(op, diff); - dc = downcount; - } else { - uint64_t dirty = flags >> 8; - if (dirty) - gstate_c.Dirty(dirty); - } - } - list.pc += 4; - } - downcount = 0; -} - void GPU_Vulkan::FinishDeferred() { drawEngine_.FinishDeferred(); } diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 2bb8b3cf26..670ff9487b 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -71,7 +71,6 @@ public: } protected: - void FastRunLoop(DisplayList &list) override; void FinishDeferred() override; private: From 64ec46e7050fb751d54029329421eef0cf5a5323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 11:58:17 +0100 Subject: [PATCH 190/291] Unify FramebufferDirty()/FramebufferReallyDirty() for the hw backends --- GPU/D3D11/GPU_D3D11.cpp | 20 -------------------- GPU/D3D11/GPU_D3D11.h | 2 -- GPU/Directx9/GPU_DX9.cpp | 20 -------------------- GPU/Directx9/GPU_DX9.h | 2 -- GPU/GLES/GPU_GLES.cpp | 20 -------------------- GPU/GLES/GPU_GLES.h | 2 -- GPU/GPUCommon.cpp | 20 ++++++++++++++++++++ GPU/GPUCommon.h | 3 +++ GPU/Vulkan/GPU_Vulkan.cpp | 20 -------------------- GPU/Vulkan/GPU_Vulkan.h | 2 -- 10 files changed, 23 insertions(+), 88 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 5dbe449087..ec866cc815 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -254,26 +254,6 @@ void GPU_D3D11::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat f framebufferManagerD3D11_->SetDisplayFramebuffer(framebuf, stride, format); } -bool GPU_D3D11::FramebufferDirty() { - VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); - if (vfb) { - bool dirty = vfb->dirtyAfterDisplay; - vfb->dirtyAfterDisplay = false; - return dirty; - } - return true; -} - -bool GPU_D3D11::FramebufferReallyDirty() { - VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); - if (vfb) { - bool dirty = vfb->reallyDirtyAfterDisplay; - vfb->reallyDirtyAfterDisplay = false; - return dirty; - } - return true; -} - void GPU_D3D11::CopyDisplayToOutput() { float blendColor[4]{}; context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], blendColor, 0xFFFFFFFF); diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index aadaef4556..e716906f83 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -50,8 +50,6 @@ public: void DoState(PointerWrap &p) override; void ClearShaderCache() override; - bool FramebufferDirty() override; - bool FramebufferReallyDirty() override; void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override { primaryInfo = reportingPrimaryInfo_; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 32c03fd030..590c7ac135 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -230,26 +230,6 @@ void GPU_DX9::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat for framebufferManagerDX9_->SetDisplayFramebuffer(framebuf, stride, format); } -bool GPU_DX9::FramebufferDirty() { - VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); - if (vfb) { - bool dirty = vfb->dirtyAfterDisplay; - vfb->dirtyAfterDisplay = false; - return dirty; - } - return true; -} - -bool GPU_DX9::FramebufferReallyDirty() { - VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); - if (vfb) { - bool dirty = vfb->reallyDirtyAfterDisplay; - vfb->reallyDirtyAfterDisplay = false; - return dirty; - } - return true; -} - void GPU_DX9::CopyDisplayToOutput() { dxstate.depthWrite.set(true); dxstate.colorMask.set(true, true, true, true); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 2681bd4c79..d72e2c4321 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -51,8 +51,6 @@ public: void DoState(PointerWrap &p) override; void ClearShaderCache() override; - bool FramebufferDirty() override; - bool FramebufferReallyDirty() override; void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override { primaryInfo = reportingPrimaryInfo_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 44962d935a..07a15b7960 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -440,26 +440,6 @@ void GPU_GLES::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat fo framebufferManagerGL_->SetDisplayFramebuffer(framebuf, stride, format); } -bool GPU_GLES::FramebufferDirty() { - VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB(); - if (vfb) { - bool dirty = vfb->dirtyAfterDisplay; - vfb->dirtyAfterDisplay = false; - return dirty; - } - return true; -} - -bool GPU_GLES::FramebufferReallyDirty() { - VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB(); - if (vfb) { - bool dirty = vfb->reallyDirtyAfterDisplay; - vfb->reallyDirtyAfterDisplay = false; - return dirty; - } - return true; -} - void GPU_GLES::CopyDisplayToOutput() { // Flush anything left over. framebufferManagerGL_->RebindFramebuffer(); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index b81f349dd5..4ea7a62064 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -55,8 +55,6 @@ public: void ClearShaderCache() override; void CleanupBeforeUI() override; - bool FramebufferDirty() override; - bool FramebufferReallyDirty() override; void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override { primaryInfo = reportingPrimaryInfo_; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index fc9bf6b62a..782b2a324d 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2598,3 +2598,23 @@ bool GPUCommon::DescribeCodePtr(const u8 *ptr, std::string &name) { } return false; } + +bool GPUCommon::FramebufferDirty() { + VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); + if (vfb) { + bool dirty = vfb->dirtyAfterDisplay; + vfb->dirtyAfterDisplay = false; + return dirty; + } + return true; +} + +bool GPUCommon::FramebufferReallyDirty() { + VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); + if (vfb) { + bool dirty = vfb->reallyDirtyAfterDisplay; + vfb->reallyDirtyAfterDisplay = false; + return dirty; + } + return true; +} diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index e83c499d79..2f49863b7f 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -245,6 +245,9 @@ public: return -1; } + bool FramebufferDirty() override; + bool FramebufferReallyDirty() override; + typedef void (GPUCommon::*CmdFunc)(u32 op, u32 diff); protected: diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index a95e93d911..0aeefe8495 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -345,26 +345,6 @@ void GPU_Vulkan::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat framebufferManager_->SetDisplayFramebuffer(framebuf, stride, format); } -bool GPU_Vulkan::FramebufferDirty() { - VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); - if (vfb) { - bool dirty = vfb->dirtyAfterDisplay; - vfb->dirtyAfterDisplay = false; - return dirty; - } - return true; -} - -bool GPU_Vulkan::FramebufferReallyDirty() { - VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); - if (vfb) { - bool dirty = vfb->reallyDirtyAfterDisplay; - vfb->reallyDirtyAfterDisplay = false; - return dirty; - } - return true; -} - void GPU_Vulkan::CopyDisplayToOutput() { // Flush anything left over. drawEngine_.Flush(); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 670ff9487b..266fe01485 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -54,8 +54,6 @@ public: void DoState(PointerWrap &p) override; void ClearShaderCache() override; - bool FramebufferDirty() override; - bool FramebufferReallyDirty() override; void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override { primaryInfo = reportingPrimaryInfo_; From 0b4b2bfe9c8144b2c186aa3d318b5ead3000ef63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 13:51:14 +0100 Subject: [PATCH 191/291] Avoid the most common virtual call when possible. --- GPU/Common/DrawEngineCommon.h | 3 +++ GPU/GPUCommon.cpp | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 10af8ca780..b99bc12cea 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -79,6 +79,9 @@ public: bool IsCodePtrVertexDecoder(const u8 *ptr) const { return decJitCache_->IsInSpace(ptr); } + int GetNumDrawCalls() const { + return numDrawCalls; + } protected: virtual void ClearTrackedVertexArrays() {} diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 782b2a324d..d30ba2cfdf 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -985,7 +985,9 @@ void GPUCommon::FastRunLoop(DisplayList &list) { } else { uint64_t flags = info.flags; if (flags & FLAG_FLUSHBEFOREONCHANGE) { - drawEngineCommon_->DispatchFlush(); + if (drawEngineCommon_->GetNumDrawCalls()) { + drawEngineCommon_->DispatchFlush(); + } } gstate.cmdmem[cmd] = op; if (flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) { From 375fa3fb5bc56248c79c784bceefcf42cabdf818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 14:23:19 +0100 Subject: [PATCH 192/291] Improve a bunch of Vulkan copy-rect asserts by adding more debug info --- ext/native/thin3d/VulkanRenderManager.cpp | 26 ++++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 9ae9f4ae6d..068b3419e9 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -1,4 +1,6 @@ #include + +#include "Common/Log.h" #include "base/logging.h" #include "Common/Vulkan/VulkanContext.h" @@ -631,12 +633,16 @@ void VulkanRenderManager::Clear(uint32_t clearColor, float clearZ, int clearSten } void VulkanRenderManager::CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, VKRFramebuffer *dst, VkOffset2D dstPos, int aspectMask) { - _dbg_assert_msg_(G3D, srcRect.offset.x >= 0, "srcrect offset x < 0"); - _dbg_assert_msg_(G3D, srcRect.offset.y >= 0, "srcrect offset y < 0"); - _dbg_assert_msg_(G3D, srcRect.offset.x + srcRect.extent.width <= (uint32_t)src->width, "srcrect offset x + extent > width"); - _dbg_assert_msg_(G3D, srcRect.offset.y + srcRect.extent.height <= (uint32_t)src->height, "srcrect offset y + extent > height"); - _dbg_assert_msg_(G3D, dstPos.x >= 0, "dstPos offset x < 0"); - _dbg_assert_msg_(G3D, dstPos.y >= 0, "dstPos offset y < 0"); + _dbg_assert_msg_(G3D, srcRect.offset.x >= 0, "srcrect offset x (%d) < 0", srcRect.offset.x); + _dbg_assert_msg_(G3D, srcRect.offset.y >= 0, "srcrect offset y (%d) < 0", srcRect.offset.y); + _dbg_assert_msg_(G3D, srcRect.offset.x + srcRect.extent.width <= (uint32_t)src->width, "srcrect offset x (%d) + extent (%d) > width (%d)", srcRect.offset.x, srcRect.extent.width, (uint32_t)src->width); + _dbg_assert_msg_(G3D, srcRect.offset.y + srcRect.extent.height <= (uint32_t)src->height, "srcrect offset y (%d) + extent (%d) > height (%d)", srcRect.offset.y, srcRect.extent.height, (uint32_t)src->height); + + _dbg_assert_msg_(G3D, srcRect.extent.width > 0, "copy srcwidth == 0"); + _dbg_assert_msg_(G3D, srcRect.extent.height > 0, "copy srcheight == 0"); + + _dbg_assert_msg_(G3D, dstPos.x >= 0, "dstPos offset x (%d) < 0", dstPos.x); + _dbg_assert_msg_(G3D, dstPos.y >= 0, "dstPos offset y (%d) < 0", dstPos.y); _dbg_assert_msg_(G3D, dstPos.x + srcRect.extent.width <= (uint32_t)dst->width, "dstPos + extent x > width"); _dbg_assert_msg_(G3D, dstPos.y + srcRect.extent.height <= (uint32_t)dst->height, "dstPos + extent y > height"); @@ -654,10 +660,10 @@ void VulkanRenderManager::CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, } void VulkanRenderManager::BlitFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, VKRFramebuffer *dst, VkRect2D dstRect, int aspectMask, VkFilter filter) { - _dbg_assert_msg_(G3D, srcRect.offset.x >= 0, "srcrect offset x < 0"); - _dbg_assert_msg_(G3D, srcRect.offset.y >= 0, "srcrect offset y < 0"); - _dbg_assert_msg_(G3D, srcRect.offset.x + srcRect.extent.width <= (uint32_t)src->width, "srcrect offset x + extent > width"); - _dbg_assert_msg_(G3D, srcRect.offset.y + srcRect.extent.height <= (uint32_t)src->height, "srcrect offset y + extent > height"); + _dbg_assert_msg_(G3D, srcRect.offset.x >= 0, "srcrect offset x (%d) < 0", srcRect.offset.x); + _dbg_assert_msg_(G3D, srcRect.offset.y >= 0, "srcrect offset y (%d) < 0", srcRect.offset.y); + _dbg_assert_msg_(G3D, srcRect.offset.x + srcRect.extent.width <= (uint32_t)src->width, "srcrect offset x (%d) + extent (%d) > width (%d)", srcRect.offset.x, srcRect.extent.width, (uint32_t)src->width); + _dbg_assert_msg_(G3D, srcRect.offset.y + srcRect.extent.height <= (uint32_t)src->height, "srcrect offset y (%d) + extent (%d) > height (%d)", srcRect.offset.y, srcRect.extent.height, (uint32_t)src->height); _dbg_assert_msg_(G3D, srcRect.extent.width > 0, "blit srcwidth == 0"); _dbg_assert_msg_(G3D, srcRect.extent.height > 0, "blit srcheight == 0"); From a78365e73d68c45a7b9a3707b98952cb2d8dc6ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 15:19:11 +0100 Subject: [PATCH 193/291] Remove duplicate declaration of GPUCommon::CmdFunc --- GPU/GPU.cpp | 2 +- GPU/GPUCommon.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/GPU/GPU.cpp b/GPU/GPU.cpp index 847e25661f..abccdf6da9 100644 --- a/GPU/GPU.cpp +++ b/GPU/GPU.cpp @@ -110,6 +110,6 @@ bool GPU_Init(GraphicsContext *ctx, Draw::DrawContext *draw) { void GPU_Shutdown() { delete gpu; - gpu = 0; + gpu = nullptr; gpuDebug = 0; } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 2f49863b7f..e520b38e15 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -300,7 +300,6 @@ protected: GraphicsContext *gfxCtx_; Draw::DrawContext *draw_; - typedef void (GPUCommon::*CmdFunc)(u32 op, u32 diff); struct CommandInfo { uint64_t flags; GPUCommon::CmdFunc func; From 10be0cad96f9a48b510254c9050f03748ac2b1eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 15:48:45 +0100 Subject: [PATCH 194/291] GL: Don't wait-for-idle when shutting down the PSP GPU, it's the wrong place. Should fix #10652 --- GPU/GLES/GPU_GLES.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 4ca8419772..2fb3043cf8 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -184,10 +184,6 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) } GPU_GLES::~GPU_GLES() { - GLRenderManager *render = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - render->Wipe(); - render->WaitUntilQueueIdle(); - framebufferManagerGL_->DestroyAllFBOs(); shaderManagerGL_->ClearCache(true); depalShaderCache_.Clear(); From 14c93bdc2b83c4b57d08aaaff151625f143cc1dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Feb 2018 16:39:38 +0100 Subject: [PATCH 195/291] Minor code/logging cleanups. --- Core/Core.cpp | 2 +- Core/HLE/sceKernelModule.cpp | 1 + GPU/Common/DrawEngineCommon.cpp | 27 +++++++++++---------------- GPU/Common/DrawEngineCommon.h | 1 - GPU/GPUCommon.h | 2 +- UI/NativeApp.cpp | 2 +- Windows/MainWindow.cpp | 4 +--- 7 files changed, 16 insertions(+), 23 deletions(-) diff --git a/Core/Core.cpp b/Core/Core.cpp index a65c17e944..d549d79c4f 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -177,7 +177,7 @@ bool UpdateScreenScale(int width, int height) { dp_yres = new_dp_yres; pixel_xres = width; pixel_yres = height; - INFO_LOG(SYSTEM, "pixel_res: %dx%d. Calling NativeResized()", pixel_xres, pixel_yres); + DEBUG_LOG(SYSTEM, "pixel_res: %dx%d. Calling NativeResized()", pixel_xres, pixel_yres); NativeResized(); return true; } diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 47a9ae7d84..adda9bd383 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1577,6 +1577,7 @@ void __KernelLoadReset() { HLEShutdown(); Replacement_Init(); HLEInit(); + assert(gpu); gpu->Reinitialize(); } diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 1f6a44eda2..abba527ef2 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -330,11 +330,12 @@ bool DrawEngineCommon::GetCurrentSimpleVertices(int count, std::vector> GE_VTYPE_IDX_SHIFT; dc.prim = prim; dc.vertexCount = vertexCount; if (g_Config.bVertexCache) { u32 dhash = dcid_; - dhash ^= (u32)(uintptr_t)verts; - dhash = __rotl(dhash, 13); - dhash ^= (u32)(uintptr_t)inds; - dhash = __rotl(dhash, 13); - dhash ^= (u32)vertType; - dhash = __rotl(dhash, 13); - dhash ^= (u32)vertexCount; - dhash = __rotl(dhash, 13); - dhash ^= (u32)prim; - dcid_ = dhash; + dhash = __rotl(dhash ^ (u32)(uintptr_t)verts, 13); + dhash = __rotl(dhash ^ (u32)(uintptr_t)inds, 13); + dhash = __rotl(dhash ^ (u32)vertType, 13); + dhash = __rotl(dhash ^ (u32)vertexCount, 13); + dcid_ = dhash ^ (u32)prim;; } if (inds) { diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index b99bc12cea..64ef9ae9dc 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -132,7 +132,6 @@ protected: struct DeferredDrawCall { void *verts; void *inds; - u32 vertType; u8 indexType; s8 prim; u32 vertexCount; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index e520b38e15..5b6b78ce43 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -32,7 +32,7 @@ enum DrawType { enum { FLAG_FLUSHBEFORE = 1, FLAG_FLUSHBEFOREONCHANGE = 2, - FLAG_EXECUTE = 4, // needs to actually be executed. unused for now. + FLAG_EXECUTE = 4, FLAG_EXECUTEONCHANGE = 8, FLAG_READS_PC = 16, FLAG_WRITES_PC = 32, diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 7c95f1388d..59344be74e 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1107,7 +1107,7 @@ void NativeShutdown() { #endif g_Config.Save(); - // Avoid shutting this down when restaring core. + // Avoid shutting this down when restarting core. if (!restarting) LogManager::Shutdown(); diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 11edd34f7a..f15bcfe3a5 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -263,8 +263,6 @@ namespace MainWindow // Moves the internal display window to match the inner size of the main window. MoveWindow(hwndDisplay, 0, 0, width, height, TRUE); - INFO_LOG(SYSTEM, "New width/height: %dx%d", width, height); - // Setting pixelWidth to be too small could have odd consequences. if (width >= 4 && height >= 4) { // The framebuffer manager reads these once per frame, hopefully safe enough.. should really use a mutex or some @@ -273,7 +271,7 @@ namespace MainWindow PSP_CoreParameter().pixelHeight = height; } - INFO_LOG(SYSTEM, "Pixel width/height: %dx%d", PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); + DEBUG_LOG(SYSTEM, "Pixel width/height: %dx%d", PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); if (UpdateScreenScale(width, height)) { NativeMessageReceived("gpu_resized", ""); From adc9beefc62a4ce2fe359b54ccd4cc8ba88e3ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 27 Feb 2018 20:04:41 +0100 Subject: [PATCH 196/291] UWP buildfix? --- UWP/PPSSPP_UWPMain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index d2d805cde7..994871cff1 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -20,6 +20,7 @@ #include "net/resolve.h" #include "base/display.h" #include "thread/threadutil.h" +#include "thin3d/thin3d_create.h" #include "util/text/utf8.h" #include "Common/DirectXHelper.h" #include "NKCodeFromWindowsSystem.h" From f5dd9c17cdcb8440e2e7fe5c6a007bc42f8aedfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 27 Feb 2018 20:40:44 +0100 Subject: [PATCH 197/291] Add comment trying to clarify shutdown of GPU_GLES, restore the wipe, minor tweaks. Should help #10652 This reverts commit 10be0cad96f9a48b510254c9050f03748ac2b1eb. --- GPU/Common/DrawEngineCommon.cpp | 2 +- GPU/GLES/GPU_GLES.cpp | 6 ++++++ ext/native/thin3d/thin3d_gl.cpp | 5 ++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index abba527ef2..166cd9a659 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -701,7 +701,7 @@ void DrawEngineCommon::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, dhash = __rotl(dhash ^ (u32)(uintptr_t)inds, 13); dhash = __rotl(dhash ^ (u32)vertType, 13); dhash = __rotl(dhash ^ (u32)vertexCount, 13); - dcid_ = dhash ^ (u32)prim;; + dcid_ = dhash ^ (u32)prim; } if (inds) { diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 477f507344..ea65a9faec 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -120,6 +120,12 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) } GPU_GLES::~GPU_GLES() { + GLRenderManager *render = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + render->Wipe(); + + // If we're here during app shutdown (exiting the Windows app in-game, for example) + // everything should already be cleared since DeviceLost has been run. + framebufferManagerGL_->DestroyAllFBOs(); shaderManagerGL_->ClearCache(true); depalShaderCache_.Clear(); diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 0b6f216891..5ef1af4874 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -231,7 +231,7 @@ GLuint ShaderStageToOpenGL(ShaderStage stage) { class OpenGLShaderModule : public ShaderModule { public: OpenGLShaderModule(GLRenderManager *render, ShaderStage stage) : render_(render), stage_(stage) { - ILOG("Shader module created (%p)", this); + DLOG("Shader module created (%p)", this); glstage_ = ShaderStageToOpenGL(stage); } @@ -297,7 +297,7 @@ public: OpenGLPipeline(GLRenderManager *render) : render_(render) { } ~OpenGLPipeline() { - ILOG("OpenGLPipeline released"); + DLOG("OpenGLPipeline released"); for (auto &iter : shaders) { iter->Release(); } @@ -633,7 +633,6 @@ OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : bool genMips = false; if ((int)desc.initData.size() < desc.mipLevels && desc.generateMips) { - ILOG("Generating mipmaps"); // Assumes the texture is bound for editing genMips = true; generatedMips_ = true; From 07afda1db0670c9a093f320a8f48eedbe689c7bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 28 Feb 2018 01:01:45 +0100 Subject: [PATCH 198/291] Add an extra check to FindTransferFramebuffers to avoid misdetecting fb blits that end up out of bounds when we perform them. Affected Burnout Legends (which would crash the Vulkan device) --- GPU/Common/FramebufferCommon.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index fd2bf19ec4..ff3a131190 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -1352,9 +1352,10 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst const u32 byteOffset = dstBasePtr - vfb_address; const u32 byteStride = dstStride * bpp; const u32 yOffset = byteOffset / byteStride; + // Some games use mismatching bitdepths. But make sure the stride matches. // If it doesn't, generally this means we detected the framebuffer with too large a height. - bool match = yOffset < dstYOffset; + bool match = yOffset < dstYOffset && yOffset < vfb->height; if (match && vfb_byteStride != byteStride) { // Grand Knights History copies with a mismatching stride but a full line at a time. // Makes it hard to detect the wrong transfers in e.g. God of War. @@ -1384,7 +1385,7 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst const u32 byteOffset = srcBasePtr - vfb_address; const u32 byteStride = srcStride * bpp; const u32 yOffset = byteOffset / byteStride; - bool match = yOffset < srcYOffset; + bool match = yOffset < srcYOffset && yOffset < vfb->height; if (match && vfb_byteStride != byteStride) { if (width != srcStride || (byteStride * height != vfb_byteStride && byteStride * height != vfb_byteWidth)) { match = false; From 292f116821bdbdb866883c85a80c38b3a6c2de9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 28 Feb 2018 00:01:02 +0100 Subject: [PATCH 199/291] Execute_Prim: Add a smaller "inner interpreter" to avoid going back to the runloop during long sequences of PRIM commands. Helps performance by a quite measurable 1-4% in several PRIM-heavy games. --- GPU/GPUCommon.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index d30ba2cfdf..7489d4da44 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1062,7 +1062,6 @@ void GPUCommon::UpdatePC(u32 currentPC, u32 newPC) { } // Exit the runloop and recalculate things. This happens a lot in some games. - // No need to lock, this function is always called under listLock. if (currentList) downcount = currentList->stall == 0 ? 0x0FFFFFFF : (currentList->stall - newPC) / 4; else @@ -1505,7 +1504,7 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { void *verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); void *inds = 0; u32 vertexType = gstate.vertType; - if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { + if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { u32 indexAddr = gstate_c.indexAddr; if (!Memory::IsValidAddress(indexAddr)) { ERROR_LOG_REPORT(G3D, "Bad index address %08x!", indexAddr); @@ -1523,17 +1522,90 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) { vertexCost_ = EstimatePerVertexCost(); } - gpuStats.vertexGPUCycles += vertexCost_ * count; - cyclesExecuted += vertexCost_* count; int bytesRead = 0; UpdateUVScaleOffset(); - drawEngineCommon_->SubmitPrim(verts, inds, prim, count, vertexType, &bytesRead); + drawEngineCommon_->SubmitPrim(verts, inds, prim, count, vertexType, &bytesRead); // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). // Some games rely on this, they don't bother reloading VADDR and IADDR. // The VADDR/IADDR registers are NOT updated. AdvanceVerts(vertexType, count, bytesRead); + int totalVertCount = count; + + // PRIMs are often followed by more PRIMs. Save some work and submit them immediately. + const u32 *src = (const u32 *)Memory::GetPointerUnchecked(currentList->pc + 4); + const u32 *stall = currentList->stall ? (const u32 *)Memory::GetPointerUnchecked(currentList->stall) : 0; + int cmdCount = 0; + + // Optimized submission of sequences of PRIM. Allows us to avoid going through all the mess + // above for each one. This can be expanded to support additional games that intersperse + // PRIM commands with other commands. A special case that might be interesting is that game + // that changes culling mode between each prim, we could just change the triangle winding + // right here to still be able to join draw calls. + while (src != stall) { + uint32_t data = *src; + switch (data >> 24) { + case GE_CMD_PRIM: + { + u32 count = data & 0xFFFF; + if (count == 0) { + break; + } + + GEPrimitiveType newPrim = static_cast((data >> 16) & 7); + // Can be more lenient later. + if (newPrim != prim) { + goto bail; + } + // TODO: more efficient updating of verts/inds + verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); + inds = 0; + if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { + u32 indexAddr = gstate_c.indexAddr; + if (!Memory::IsValidAddress(indexAddr)) { + ERROR_LOG_REPORT(G3D, "Bad index address %08x!", indexAddr); + return; + } + inds = Memory::GetPointerUnchecked(indexAddr); + } + + drawEngineCommon_->SubmitPrim(verts, inds, newPrim, count, vertexType, &bytesRead); + AdvanceVerts(vertexType, count, bytesRead); + totalVertCount += count; + break; + } + case GE_CMD_VERTEXTYPE: + // Some games spam redundant GE_CMD_VERTEXTYPE + if (data != vertexType) { // don't mask data, vertexType is unmasked + goto bail; + } + break; + case GE_CMD_VADDR: + gstate_c.vertexAddr = gstate_c.getRelativeAddress(data & 0x00FFFFFF); + break; + case GE_CMD_BASE: + gstate.cmdmem[GE_CMD_BASE] = data; + break; + case GE_CMD_NOP_FF: + break; + default: + // All other commands might need a flush or something, stop this inner loop. + goto bail; + } + cmdCount++; + src++; + } + +bail: + // Skip over the commands we just read out manually. + if (cmdCount > 0) { + UpdatePC(currentList->pc, currentList->pc + cmdCount * 4); + currentList->pc += cmdCount * 4; + } + + gpuStats.vertexGPUCycles += vertexCost_ * totalVertCount; + cyclesExecuted += vertexCost_ * totalVertCount; } void GPUCommon::Execute_Bezier(u32 op, u32 diff) { From ef3341e34fd4384166f103ce925ffd25d8f6df68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 28 Feb 2018 01:26:43 +0100 Subject: [PATCH 200/291] Don't use the inner interpreter when debug recording --- GPU/GPUCommon.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 7489d4da44..70478820f4 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1543,6 +1543,9 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { // PRIM commands with other commands. A special case that might be interesting is that game // that changes culling mode between each prim, we could just change the triangle winding // right here to still be able to join draw calls. + if (debugRecording_) + goto bail; + while (src != stall) { uint32_t data = *src; switch (data >> 24) { From bc339c037751f62557adddf7120d11b2fda6642e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 28 Feb 2018 13:28:39 +0100 Subject: [PATCH 201/291] GL: Filter away redundant glEnable/Disable(GL_STENCIL_TEST) --- ext/native/thin3d/GLQueueRunner.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 360fa54dd0..93821b953f 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -512,6 +512,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { GLuint curArrayBuffer = (GLuint)-1; GLuint curElemArrayBuffer = (GLuint)-1; bool depthEnabled = false; + bool stencilEnabled = false; bool blendEnabled = false; bool cullEnabled = false; bool ditherEnabled = false; @@ -545,10 +546,14 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { break; case GLRRenderCommand::STENCILFUNC: if (c.stencilFunc.enabled) { - glEnable(GL_STENCIL_TEST); + if (!stencilEnabled) { + glEnable(GL_STENCIL_TEST); + stencilEnabled = true; + } glStencilFunc(c.stencilFunc.func, c.stencilFunc.ref, c.stencilFunc.compareMask); - } else { + } else if (stencilEnabled) { glDisable(GL_STENCIL_TEST); + stencilEnabled = false; } break; case GLRRenderCommand::STENCILOP: From 83c82a5ebd991b462187065ca5c6c7fa4e9f0649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 28 Feb 2018 18:45:14 +0100 Subject: [PATCH 202/291] GL: Fix depal issue where we forgot to set vp/scissor properly. Update some asserts. --- Common/Vulkan/VulkanMemory.cpp | 11 ++++------- GPU/GLES/TextureCacheGLES.cpp | 2 ++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Common/Vulkan/VulkanMemory.cpp b/Common/Vulkan/VulkanMemory.cpp index 1e7929202e..4107089463 100644 --- a/Common/Vulkan/VulkanMemory.cpp +++ b/Common/Vulkan/VulkanMemory.cpp @@ -135,14 +135,14 @@ size_t VulkanPushBuffer::GetTotalSize() const { } void VulkanPushBuffer::Map() { - assert(!writePtr_); + _dbg_assert_(G3D, !writePtr_); VkResult res = vkMapMemory(device_, buffers_[buf_].deviceMemory, 0, size_, 0, (void **)(&writePtr_)); - assert(writePtr_); + _dbg_assert_(G3D, writePtr_); assert(VK_SUCCESS == res); } void VulkanPushBuffer::Unmap() { - assert(writePtr_); + _dbg_assert_(G3D, writePtr_ != 0); /* // Should not need this since we use coherent memory. VkMappedMemoryRange range{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE }; @@ -366,10 +366,7 @@ void VulkanDeviceAllocator::ExecuteFree(FreeInfo *userdata) { } // Wrong deviceMemory even? Maybe it was already decimated, but that means a double-free. - if (!found) { - Crash(); - } - + _assert_msg_(G3D, found, "ExecuteFree: Block not found (offset %d)", (int)offset); delete userdata; } diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 6aa92b3f5e..d3efe107ca 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -441,6 +441,8 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); shaderManager_->DirtyLastShader(); + render_->SetScissor(GLRect2D{ 0, 0, (uint32_t)framebuffer->renderWidth, (uint32_t)framebuffer->renderHeight }); + render_->SetViewport(GLRViewport{ 0.0f, 0.0f, (float)framebuffer->renderWidth, (float)framebuffer->renderHeight, 0.0f, 1.0f }); TextureShaderApplier shaderApply(depal, framebuffer->bufferWidth, framebuffer->bufferHeight, framebuffer->renderWidth, framebuffer->renderHeight); shaderApply.ApplyBounds(gstate_c.vertBounds, gstate_c.curTextureXOffset, gstate_c.curTextureYOffset); shaderApply.Use(render_, drawEngine_, shadeInputLayout_); From 28e202a089d08fd322d1f9f3b23ad204619d639a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 28 Feb 2018 19:15:29 +0100 Subject: [PATCH 203/291] Buildfix, oops --- GPU/GLES/TextureCacheGLES.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index d3efe107ca..376cb5b1ee 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -441,7 +441,7 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); shaderManager_->DirtyLastShader(); - render_->SetScissor(GLRect2D{ 0, 0, (uint32_t)framebuffer->renderWidth, (uint32_t)framebuffer->renderHeight }); + render_->SetScissor(GLRect2D{ 0, 0, (int)framebuffer->renderWidth, (int)framebuffer->renderHeight }); render_->SetViewport(GLRViewport{ 0.0f, 0.0f, (float)framebuffer->renderWidth, (float)framebuffer->renderHeight, 0.0f, 1.0f }); TextureShaderApplier shaderApply(depal, framebuffer->bufferWidth, framebuffer->bufferHeight, framebuffer->renderWidth, framebuffer->renderHeight); shaderApply.ApplyBounds(gstate_c.vertBounds, gstate_c.curTextureXOffset, gstate_c.curTextureYOffset); From 3b0d307792fd59ce423f07da2a760d2f7d883c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 13:12:46 +0100 Subject: [PATCH 204/291] Fix something found by -fsanitize=undefined --- ext/native/thin3d/thin3d.cpp | 1 + ext/native/ui/viewgroup.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/native/thin3d/thin3d.cpp b/ext/native/thin3d/thin3d.cpp index 98827edda9..b877eb6765 100644 --- a/ext/native/thin3d/thin3d.cpp +++ b/ext/native/thin3d/thin3d.cpp @@ -399,6 +399,7 @@ void ConvertFromRGBA8888(uint8_t *dst, const uint8_t *src, uint32_t dstStride, u break; case Draw::DataFormat::R8G8B8A8_UNORM: case Draw::DataFormat::UNDEFINED: + default: // Not possible. break; } diff --git a/ext/native/ui/viewgroup.cpp b/ext/native/ui/viewgroup.cpp index b6e9c08dcc..ab748a9772 100644 --- a/ext/native/ui/viewgroup.cpp +++ b/ext/native/ui/viewgroup.cpp @@ -461,7 +461,6 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v allowedWidth = horiz.size; } - float unit = (allowedWidth - weightZeroSum) / weightSum; float usedWidth = 0.0f; // Redistribute the stretchy ones! and remeasure the children! @@ -477,6 +476,7 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v MeasureSpec v = vert; if (v.type == UNSPECIFIED && measuredHeight_ != 0.0f) v = MeasureSpec(AT_MOST, measuredHeight_); + float unit = (allowedWidth - weightZeroSum) / weightSum; MeasureSpec h(AT_MOST, unit * linLayoutParams->weight - margins.horiz()); if (horiz.type == EXACTLY) { h.type = EXACTLY; @@ -502,7 +502,6 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v allowedHeight = vert.size; } - float unit = (allowedHeight - weightZeroSum) / weightSum; float usedHeight = 0.0f; // Redistribute the stretchy ones! and remeasure the children! @@ -518,6 +517,7 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v MeasureSpec h = horiz; if (h.type == UNSPECIFIED && measuredWidth_ != 0.0f) h = MeasureSpec(AT_MOST, measuredWidth_); + float unit = (allowedHeight - weightZeroSum) / weightSum; MeasureSpec v(AT_MOST, unit * linLayoutParams->weight - margins.vert()); if (vert.type == EXACTLY) { v.type = EXACTLY; From 7bedbe4e15c48d9e05634cbd4f5517d90004f960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 1 Mar 2018 08:37:13 +0100 Subject: [PATCH 205/291] b.sh: Add --qtbrew as a shortcut to use a Qt installed by homebrew. --- b.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/b.sh b/b.sh index f074ff0952..dbd616245f 100755 --- a/b.sh +++ b/b.sh @@ -9,6 +9,10 @@ do QT=1 CMAKE_ARGS="-DUSING_QT_UI=ON ${CMAKE_ARGS}" ;; + --qtbrew) echo "Qt enabled (homebrew)" + QT=1 + CMAKE_ARGS="-DUSING_QT_UI=ON -DCMAKE_PREFIX_PATH=$(brew --prefix qt5) ${CMAKE_ARGS}" + ;; --ios) CMAKE_ARGS="-DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/ios.cmake ${CMAKE_ARGS}" TARGET_OS=iOS ;; From ebb819b5cc860f8e620542b096dd787a4d1acc76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 1 Mar 2018 08:46:22 +0100 Subject: [PATCH 206/291] Qt: Don't call SDL_PumpEvents from the emu thread. Fixes #10660 --- Qt/QtMain.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 297a31c661..5112c20435 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -199,9 +199,6 @@ void MainUI::EmuThreadFunc() { emuThreadState = (int)EmuThreadState::RUNNING; while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) { - #ifdef SDL - SDL_PumpEvents(); - #endif updateAccelerometer(); UpdateRunLoop(); } From 4130bcd4169e2385e628aa7ab791bed49ee52a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 28 Feb 2018 23:22:33 +0100 Subject: [PATCH 207/291] inner interpreter: support skipping regular nops --- GPU/GPUCommon.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 70478820f4..c21847d32b 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1590,6 +1590,7 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { case GE_CMD_BASE: gstate.cmdmem[GE_CMD_BASE] = data; break; + case GE_CMD_NOP: case GE_CMD_NOP_FF: break; default: From c7dcb7c3653322f3e024eb9b70975f007e69d82e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 1 Mar 2018 09:26:45 +0100 Subject: [PATCH 208/291] D3D9/D3D11: Fix GPU feature detection. Enforce accurate depth on nVidia as well, they no longer seem to support reverse depth so it's needed as a workaround. Fixes #10655 --- GPU/D3D11/GPU_D3D11.cpp | 8 ++++++-- GPU/Directx9/GPU_DX9.cpp | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index ec866cc815..8ad9ebd11a 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -104,6 +104,7 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) // No need to flush before the tex scale/offset commands if we are baking // the tex scale/offset into the vertices anyway. UpdateCmdInfo(); + CheckGPUFeatures(); BuildReportingInfo(); @@ -129,8 +130,10 @@ void GPU_D3D11::CheckGPUFeatures() { features |= GPU_SUPPORTS_BLEND_MINMAX; features |= GPU_PREFER_CPU_DOWNLOAD; - // Accurate depth is required on AMD so we ignore the compat flag to disable it on those. See #9545 - if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth || draw_->GetDeviceCaps().vendor == Draw::GPUVendor::VENDOR_AMD) { + // Accurate depth is required on AMD/nVidia (for reverse Z) so we ignore the compat flag to disable it on those. See #9545 + auto vendor = draw_->GetDeviceCaps().vendor; + + if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth || vendor == Draw::GPUVendor::VENDOR_AMD || vendor == Draw::GPUVendor::VENDOR_NVIDIA) { features |= GPU_SUPPORTS_ACCURATE_DEPTH; // Breaks text in PaRappa for some reason. } @@ -214,6 +217,7 @@ void GPU_D3D11::BeginHostFrame() { GPUCommon::BeginHostFrame(); UpdateCmdInfo(); if (resized_) { + CheckGPUFeatures(); framebufferManager_->Resized(); drawEngine_.Resized(); textureCacheD3D11_->NotifyConfigChanged(); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 590c7ac135..adb50ecbf0 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -86,6 +86,7 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) // No need to flush before the tex scale/offset commands if we are baking // the tex scale/offset into the vertices anyway. UpdateCmdInfo(); + CheckGPUFeatures(); BuildReportingInfo(); @@ -111,8 +112,9 @@ void GPU_DX9::CheckGPUFeatures() { features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL; features |= GPU_PREFER_CPU_DOWNLOAD; - // Accurate depth is required on AMD so we ignore the compat flag to disable it on those. See #9545 - if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth || draw_->GetDeviceCaps().vendor == Draw::GPUVendor::VENDOR_AMD) { + auto vendor = draw_->GetDeviceCaps().vendor; + // Accurate depth is required on AMD/nVidia (for reverse Z) so we ignore the compat flag to disable it on those. See #9545 + if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth || vendor == Draw::GPUVendor::VENDOR_AMD || vendor == Draw::GPUVendor::VENDOR_NVIDIA) { features |= GPU_SUPPORTS_ACCURATE_DEPTH; } @@ -191,6 +193,7 @@ void GPU_DX9::BeginHostFrame() { GPUCommon::BeginHostFrame(); UpdateCmdInfo(); if (resized_) { + CheckGPUFeatures(); framebufferManager_->Resized(); drawEngine_.Resized(); shaderManagerDX9_->DirtyShader(); From ee752f5399d67f3c0bdb58333a17091ea97ef71f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 1 Mar 2018 12:11:10 +0100 Subject: [PATCH 209/291] Some error handling and assert improvements, trying to understand #10662 --- Common/Vulkan/VulkanImage.cpp | 18 +++++++++++------- UI/TextureUtil.cpp | 5 ++--- ext/native/thin3d/thin3d_vulkan.cpp | 17 +++++++++++++---- ext/native/ui/ui_context.cpp | 2 +- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index 9551a1704a..597907bb70 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -60,7 +60,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, VkResult res = vkCreateImage(vulkan_->GetDevice(), &image_create_info, NULL, &image_); if (res != VK_SUCCESS) { - assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); + _assert_(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); return false; } @@ -79,12 +79,14 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, // Find memory type - don't specify any mapping requirements bool pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mem_alloc.memoryTypeIndex); - assert(pass); + _assert_(pass); res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mem_); if (res != VK_SUCCESS) { _assert_msg_(G3D, res != VK_ERROR_TOO_MANY_OBJECTS, "Too many Vulkan memory objects!"); - assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); + _assert_(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); + vkDestroyImage(vulkan_->GetDevice(), image_, nullptr); + image_ = nullptr; return false; } @@ -93,7 +95,8 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, res = vkBindImageMemory(vulkan_->GetDevice(), image_, mem_, offset_); if (res != VK_SUCCESS) { - assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); + // This leaks the image and memory. Should not really happen though... + _assert_(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); return false; } @@ -108,8 +111,8 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, break; default: // If you planned to use UploadMip, you want VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL. After the - // upload, you can transition. - assert(false); + // upload, you can transition using EndCreate. + _assert_(false); break; } } @@ -135,7 +138,8 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, res = vkCreateImageView(vulkan_->GetDevice(), &view_info, NULL, &view_); if (res != VK_SUCCESS) { - assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); + // This leaks the image. + _assert_(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); return false; } return true; diff --git a/UI/TextureUtil.cpp b/UI/TextureUtil.cpp index 6ee742751b..4855dd6e41 100644 --- a/UI/TextureUtil.cpp +++ b/UI/TextureUtil.cpp @@ -131,8 +131,7 @@ bool ManagedTexture::LoadFromFileData(const uint8_t *data, size_t dataSize, Imag if (image[i]) free(image[i]); } - - return true; + return texture_ != nullptr; } bool ManagedTexture::LoadFromFile(const std::string &filename, ImageFileType type, bool generateMips) { @@ -172,4 +171,4 @@ std::unique_ptr CreateTextureFromFileData(Draw::DrawContext *dra ManagedTexture *mtex = new ManagedTexture(draw); mtex->LoadFromFileData(data, size, type, generateMips); return std::move(std::unique_ptr(mtex)); -} \ No newline at end of file +} diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 58cee3ee00..1f5660adfb 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -304,7 +304,7 @@ public: VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc, VulkanDeviceAllocator *alloc) : vulkan_(vulkan), mipLevels_(desc.mipLevels), format_(desc.format) { bool result = Create(cmd, pushBuffer, desc, alloc); - assert(result); + _assert_(result); } ~VKTexture() { @@ -650,8 +650,8 @@ enum class TextureState { bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushBuffer *push, const TextureDesc &desc, VulkanDeviceAllocator *alloc) { // Zero-sized textures not allowed. - assert(desc.width * desc.height * desc.depth > 0); - assert(push); + _assert_(desc.width * desc.height * desc.depth > 0); // remember to set depth to 1! + _assert_(push); format_ = desc.format; mipLevels_ = desc.mipLevels; width_ = desc.width; @@ -667,7 +667,10 @@ bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushBuffer *push, const Textur // Gonna have to generate some, which requires TRANSFER_SRC usageBits |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; } - vkTex_->CreateDirect(cmd, width_, height_, mipLevels_, vulkanFormat, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, usageBits); + if (!vkTex_->CreateDirect(cmd, width_, height_, mipLevels_, vulkanFormat, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, usageBits)) { + ELOG("Failed to create VulkanTexture: %dx%dx%d fmt %d, %d levels", width_, height_, depth_, (int)vulkanFormat, mipLevels_); + return false; + } if (desc.initData.size()) { int w = width_; int h = height_; @@ -1017,6 +1020,12 @@ InputLayout *VKContext::CreateInputLayout(const InputLayoutDesc &desc) { } Texture *VKContext::CreateTexture(const TextureDesc &desc) { + if (!push_) { + // Too early! Fail. + ELOG("Can't create textures before the first frame has started."); + return nullptr; + } + _assert_(renderManager_.GetInitCmd()); return new VKTexture(vulkan_, renderManager_.GetInitCmd(), push_, desc, allocator_); } diff --git a/ext/native/ui/ui_context.cpp b/ext/native/ui/ui_context.cpp index 6ad2d78c8c..a148a0b60d 100644 --- a/ext/native/ui/ui_context.cpp +++ b/ext/native/ui/ui_context.cpp @@ -32,7 +32,7 @@ void UIContext::Init(Draw::DrawContext *thin3d, Draw::Pipeline *uipipe, Draw::Pi void UIContext::BeginFrame() { if (!uitexture_) { - uitexture_ = CreateTextureFromFile(draw_, "ui_atlas.zim", ImageFileType::ZIM); + uitexture_ = CreateTextureFromFile(draw_, "ui_atlas.zim", ImageFileType::ZIM, false); if (!uitexture_) { PanicAlert("Failed to load ui_atlas.zim.\n\nPlace it in the directory \"assets\" under your PPSSPP directory."); FLOG("Failed to load ui_atlas.zim"); From 1e940f497369af174f97a22dc3a91c1b0cdc4301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 1 Mar 2018 13:50:56 +0100 Subject: [PATCH 210/291] Buildfix, warning fixes --- Common/Vulkan/VulkanImage.cpp | 2 +- UI/PauseScreen.cpp | 2 +- UI/TextureUtil.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index 597907bb70..a7244d6dde 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -86,7 +86,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, _assert_msg_(G3D, res != VK_ERROR_TOO_MANY_OBJECTS, "Too many Vulkan memory objects!"); _assert_(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); vkDestroyImage(vulkan_->GetDevice(), image_, nullptr); - image_ = nullptr; + image_ = VK_NULL_HANDLE; return false; } diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 03363ef4c0..433b316997 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -80,7 +80,7 @@ void AsyncImageFileView::SetFilename(std::string filename) { void AsyncImageFileView::Draw(UIContext &dc) { using namespace Draw; if (!texture_ && !textureFailed_ && !filename_.empty()) { - texture_ = std::move(CreateTextureFromFile(dc.GetDrawContext(), filename_.c_str(), DETECT, true)); + texture_ = CreateTextureFromFile(dc.GetDrawContext(), filename_.c_str(), DETECT, true); if (!texture_.get()) textureFailed_ = true; } diff --git a/UI/TextureUtil.cpp b/UI/TextureUtil.cpp index 4855dd6e41..d934f956cf 100644 --- a/UI/TextureUtil.cpp +++ b/UI/TextureUtil.cpp @@ -161,7 +161,7 @@ std::unique_ptr CreateTextureFromFile(Draw::DrawContext *draw, c delete mtex; return std::unique_ptr(); } - return std::move(std::unique_ptr(mtex)); + return std::unique_ptr(mtex); } // TODO: Remove the code duplication between this and LoadFromFileData @@ -170,5 +170,5 @@ std::unique_ptr CreateTextureFromFileData(Draw::DrawContext *dra return std::unique_ptr(); ManagedTexture *mtex = new ManagedTexture(draw); mtex->LoadFromFileData(data, size, type, generateMips); - return std::move(std::unique_ptr(mtex)); + return std::unique_ptr(mtex); } From 18db8b0bd6531cbb5f02fdb116cb99ac84c74907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 1 Mar 2018 16:08:23 +0100 Subject: [PATCH 211/291] Fix custom UI backgrounds again by initializing lazily (turned out to be the cause of #10662) --- UI/MiscScreens.cpp | 8 ++++++++ UI/NativeApp.cpp | 2 -- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 577e1cedd6..fa6980f0f4 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -71,6 +71,8 @@ static const uint32_t colors[4] = { static std::unique_ptr bgTexture; +static bool backgroundInited; + void UIBackgroundInit(UIContext &dc) { const std::string bgPng = GetSysDirectory(DIRECTORY_SYSTEM) + "background.png"; const std::string bgJpg = GetSysDirectory(DIRECTORY_SYSTEM) + "background.jpg"; @@ -82,9 +84,15 @@ void UIBackgroundInit(UIContext &dc) { void UIBackgroundShutdown() { bgTexture.reset(nullptr); + backgroundInited = false; } void DrawBackground(UIContext &dc, float alpha) { + if (!backgroundInited) { + UIBackgroundInit(dc); + backgroundInited = true; + } + static float xbase[100] = {0}; static float ybase[100] = {0}; float xres = dc.GetBounds().w; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 59344be74e..cbfceed7c2 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -664,8 +664,6 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) { screenManager->setDrawContext(g_draw); screenManager->setPostRenderCallback(&RenderOverlays, nullptr); - UIBackgroundInit(*uiContext); - #ifdef _WIN32 winAudioBackend = CreateAudioBackend((AudioBackendType)g_Config.iAudioBackend); #if PPSSPP_PLATFORM(UWP) From b74634aa3bed6d49b13b9da2994ebd6edc231955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 2 Mar 2018 07:06:58 +0100 Subject: [PATCH 212/291] Turn off the inner interpreter when stepping in the GE debugger. Fix comment. --- GPU/GPUCommon.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index c21847d32b..19524f0f6b 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -381,7 +381,7 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : memset(cmdInfo_, 0, sizeof(cmdInfo_)); - // Import both the global and local command tables, and check for dupes + // Convert the command table to a faster format, and check for dupes. std::set dupeCheck; for (size_t i = 0; i < commonCommandTableSize; i++) { const u8 cmd = commonCommandTable[i].cmd; @@ -393,6 +393,7 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : cmdInfo_[cmd].flags |= (uint64_t)commonCommandTable[i].flags | (commonCommandTable[i].dirty << 8); cmdInfo_[cmd].func = commonCommandTable[i].func; if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { + // Can't have FLAG_EXECUTE commands without a function pointer to execute. Crash(); } } @@ -1543,8 +1544,10 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { // PRIM commands with other commands. A special case that might be interesting is that game // that changes culling mode between each prim, we could just change the triangle winding // right here to still be able to join draw calls. - if (debugRecording_) +#ifndef MOBILE_DEVICE + if (debugRecording_ || host->GPUDebuggingActive()) goto bail; +#endif while (src != stall) { uint32_t data = *src; From f196a877e6ff791ba7dd2e138e538756acd2e189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 3 Mar 2018 00:00:18 +0100 Subject: [PATCH 213/291] Android: Fix fallback from Vulkan to GL. --- android/jni/AndroidVulkanContext.cpp | 9 +++++- android/jni/AndroidVulkanContext.h | 4 ++- android/jni/app-android.cpp | 30 ++++++++++--------- .../src/org/ppsspp/ppsspp/NativeActivity.java | 2 +- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/android/jni/AndroidVulkanContext.cpp b/android/jni/AndroidVulkanContext.cpp index 04481b3377..e5f4987920 100644 --- a/android/jni/AndroidVulkanContext.cpp +++ b/android/jni/AndroidVulkanContext.cpp @@ -72,12 +72,15 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, return false; } +AndroidVulkanContext::AndroidVulkanContext() { +} + AndroidVulkanContext::~AndroidVulkanContext() { delete g_Vulkan; g_Vulkan = nullptr; } -bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) { +bool AndroidVulkanContext::InitAPI() { ILOG("AndroidVulkanContext::Init"); init_glslang(); @@ -124,6 +127,10 @@ bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredB g_Vulkan = nullptr; return false; } + return true; +} + +bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) { int width = desiredBackbufferSizeX; int height = desiredBackbufferSizeY; if (!width || !height) { diff --git a/android/jni/AndroidVulkanContext.h b/android/jni/AndroidVulkanContext.h index 2c65de11c3..affc330157 100644 --- a/android/jni/AndroidVulkanContext.h +++ b/android/jni/AndroidVulkanContext.h @@ -8,9 +8,11 @@ class VulkanContext; class AndroidVulkanContext : public AndroidGraphicsContext { public: - AndroidVulkanContext() : draw_(nullptr) {} + AndroidVulkanContext(); ~AndroidVulkanContext(); + bool InitAPI(); + bool InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) override; void Shutdown() override; void SwapInterval(int interval) override; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 1e54500f0f..ad91edae81 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -431,25 +431,33 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init NativeInit(2, argv, user_data_path.c_str(), externalDir.c_str(), cacheDir.c_str()); } - // Now that we've loaded config, set javaGL. - javaGL = NativeQueryConfig("androidJavaGL") == "true"; retry: + // Now that we've loaded config, set javaGL. + javaGL = NativeQueryConfig("androidJavaGL") == "true"; switch (g_Config.iGPUBackend) { case (int)GPUBackend::OPENGL: - ILOG("NativeApp.init() -- creating OpenGL context"); useCPUThread = true; - if (javaGL) { - graphicsContext = new AndroidJavaEGLGraphicsContext(); - } else { - graphicsContext = new AndroidEGLGraphicsContext(); - } + _assert_(javaGL); + ILOG("NativeApp.init() -- creating OpenGL context (JavaGL)"); + graphicsContext = new AndroidJavaEGLGraphicsContext(); break; case (int)GPUBackend::VULKAN: + { ILOG("NativeApp.init() -- creating Vulkan context"); useCPUThread = false; // The Vulkan render manager manages its own thread. // We create and destroy the Vulkan graphics context in the "EGL" thread. + AndroidVulkanContext *ctx = new AndroidVulkanContext(); + if (!ctx->InitAPI()) { + ILOG("Failed to initialize Vulkan, switching to OpenGL"); + g_Config.iGPUBackend = (int)GPUBackend::OPENGL; + SetGPUBackend(GPUBackend::OPENGL); + goto retry; + } else { + graphicsContext = ctx; + } break; + } default: ELOG("NativeApp.init(): iGPUBackend %d not supported. Switching to OpenGL.", (int)g_Config.iGPUBackend); g_Config.iGPUBackend = (int)GPUBackend::OPENGL; @@ -931,12 +939,6 @@ retry: int tries = 0; - _assert_msg_(G3D, !graphicsContext, "Graphics context already exists entering runEGLRenderLoop - this is wrong."); - - if (vulkan) { - graphicsContext = new AndroidVulkanContext(); - } - if (!graphicsContext->InitFromRenderThread(wnd, desiredBackbufferSizeX, desiredBackbufferSizeY, backbuffer_format, androidVersion)) { ELOG("Failed to initialize graphics context."); diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 01c2a107a1..30b25854a2 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -482,7 +482,7 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C gainAudioFocus(this.audioManager, this.audioFocusChangeListener); NativeApp.audioInit(); - if (javaGL) { + if (javaGL) { mGLSurfaceView = new NativeGLView(this); nativeRenderer = new NativeRenderer(this); mGLSurfaceView.setEGLContextClientVersion(2); From 448e8fb49a7914922dab0c9a16045fb9e0fa6163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 3 Mar 2018 08:46:12 +0100 Subject: [PATCH 214/291] Split out QtHost.h from HostTypes.h --- CMakeLists.txt | 2 + Qt/Debugger/debugger_displaylist.cpp | 5 +- Qt/QtHost.cpp | 29 +++++++ Qt/QtHost.h | 119 +++++++++++++++++++++++++++ UI/HostTypes.h | 117 -------------------------- UI/NativeApp.cpp | 4 + 6 files changed, 157 insertions(+), 119 deletions(-) create mode 100644 Qt/QtHost.cpp create mode 100644 Qt/QtHost.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f7d160ece..e6f573c77f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -733,6 +733,8 @@ elseif(USING_QT_UI) ${QT_UI_GEN} Qt/QtMain.cpp Qt/QtMain.h + Qt/QtHost.cpp + Qt/QtHost.h Qt/mainwindow.cpp Qt/mainwindow.h Qt/Debugger/ctrldisasmview.cpp diff --git a/Qt/Debugger/debugger_displaylist.cpp b/Qt/Debugger/debugger_displaylist.cpp index 349dbfea80..6089c64003 100644 --- a/Qt/Debugger/debugger_displaylist.cpp +++ b/Qt/Debugger/debugger_displaylist.cpp @@ -10,8 +10,9 @@ #include "Core/Host.h" #include "base/display.h" #include "mainwindow.h" -#include "UI/HostTypes.h" -//commented out until someone bothers to maintain it +#include "Qt/QtHost.h" + +//commented out until someone bothers to maintain it (see below) //#include "GPU/GLES/VertexDecoder.h" Debugger_DisplayList::Debugger_DisplayList(DebugInterface *_cpu, Draw::DrawContext *draw, MainWindow* mainWindow_, QWidget *parent) : diff --git a/Qt/QtHost.cpp b/Qt/QtHost.cpp new file mode 100644 index 0000000000..c2ef7d2eac --- /dev/null +++ b/Qt/QtHost.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2014- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include +#include "Qt/QtHost.h" + +const char* QtHost::SymbolMapFilename(std::string currentFilename) { + std::string result = currentFilename; + size_t dot = result.rfind('.'); + if (dot == result.npos) + return (result + ".map").c_str(); + + result.replace(dot, result.npos, ".map"); + return result.c_str(); +} diff --git a/Qt/QtHost.h b/Qt/QtHost.h new file mode 100644 index 0000000000..029c0b8987 --- /dev/null +++ b/Qt/QtHost.h @@ -0,0 +1,119 @@ +// Copyright (c) 2014- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "Core/Host.h" +#include "UI/OnScreenDisplay.h" + +#include "Core/Debugger/SymbolMap.h" +#include "Qt/mainwindow.h" + +class QtHost : public Host { +public: + QtHost(MainWindow *mainWindow_) + { + mainWindow = mainWindow_; + m_GPUStep = false; + m_GPUFlag = 0; + } + + virtual void UpdateUI() override { + mainWindow->updateMenus(); + } + + virtual void UpdateMemView() override { + if(mainWindow->GetDialogMemory()) + mainWindow->GetDialogMemory()->Update(); + } + virtual void UpdateDisassembly() override { + if(mainWindow->GetDialogDisasm()) + mainWindow->GetDialogDisasm()->Update(); + if(mainWindow->GetDialogDisplaylist()) + mainWindow->GetDialogDisplaylist()->Update(); + } + + virtual void SetDebugMode(bool mode) override { + if(mainWindow->GetDialogDisasm()) + mainWindow->GetDialogDisasm()->SetDebugMode(mode); + } + + virtual bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } + virtual void ShutdownGraphics() override {} + + virtual void InitSound() override; + virtual void UpdateSound() override {} + virtual void ShutdownSound() override; + + // this is sent from EMU thread! Make sure that Host handles it properly! + virtual void BootDone() override { + g_symbolMap->SortSymbols(); + mainWindow->Notify(MainWindowMsg::BOOT_DONE); + } + + virtual bool IsDebuggingEnabled() override { +#ifdef _DEBUG + return true; +#else + return false; +#endif + } + virtual bool AttemptLoadSymbolMap() override { + return false; + // TODO: Make this work with Qt and threaded GL... not sure what's so broken. + // auto fn = SymbolMapFilename(PSP_CoreParameter().fileToStart); + // return g_symbolMap->LoadSymbolMap(fn); + } + void PrepareShutdown() { + g_symbolMap->SaveSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart)); + } + void SetWindowTitle(const char *message) override { + QString title = "PPSSPP " + QString(PPSSPP_GIT_VERSION) + " - " + QString::fromUtf8(message); + + mainWindow->setWindowTitle(title); + } + + void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override { + osm.Show(message, duration, color, -1, true, id); + } + + void SendUIMessage(const std::string &message, const std::string &value) override { + NativeMessageReceived(message.c_str(), value.c_str()); + } + + bool GPUDebuggingActive() override { + auto dialogDisplayList = mainWindow->GetDialogDisplaylist(); + if (dialogDisplayList && dialogDisplayList->isVisible()) { + if (m_GPUStep && m_GPUFlag == -1) + m_GPUFlag = 0; + + return true; + } + return false; + } + void SetGPUStep(bool value, int flag = 0, u32 data = 0) { + m_GPUStep = value; + m_GPUFlag = flag; + m_GPUData = data; + } +private: + const char* SymbolMapFilename(std::string currentFilename); + MainWindow* mainWindow; + bool m_GPUStep; + int m_GPUFlag; + u32 m_GPUData; +}; diff --git a/UI/HostTypes.h b/UI/HostTypes.h index c236a1baac..e489aa668d 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -20,11 +20,6 @@ #include "Core/Host.h" #include "UI/OnScreenDisplay.h" -#if !defined(MOBILE_DEVICE) && defined(USING_QT_UI) -#include "Core/Debugger/SymbolMap.h" -#include "Qt/mainwindow.h" -#endif - class NativeHost : public Host { public: NativeHost() {} @@ -58,115 +53,3 @@ public: NativeMessageReceived(message.c_str(), value.c_str()); } }; - -#if !defined(MOBILE_DEVICE) && defined(USING_QT_UI) -static const char* SymbolMapFilename(std::string currentFilename) -{ - std::string result = currentFilename; - size_t dot = result.rfind('.'); - if (dot == result.npos) - return (result + ".map").c_str(); - - result.replace(dot, result.npos, ".map"); - return result.c_str(); -} - -class QtHost : public Host { -public: - QtHost(MainWindow *mainWindow_) - { - mainWindow = mainWindow_; - m_GPUStep = false; - m_GPUFlag = 0; - } - - virtual void UpdateUI() override { - mainWindow->updateMenus(); - } - - virtual void UpdateMemView() override { - if(mainWindow->GetDialogMemory()) - mainWindow->GetDialogMemory()->Update(); - } - virtual void UpdateDisassembly() override { - if(mainWindow->GetDialogDisasm()) - mainWindow->GetDialogDisasm()->Update(); - if(mainWindow->GetDialogDisplaylist()) - mainWindow->GetDialogDisplaylist()->Update(); - } - - virtual void SetDebugMode(bool mode) override { - if(mainWindow->GetDialogDisasm()) - mainWindow->GetDialogDisasm()->SetDebugMode(mode); - } - - virtual bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } - virtual void ShutdownGraphics() override {} - - virtual void InitSound() override; - virtual void UpdateSound() override {} - virtual void ShutdownSound(); - - // this is sent from EMU thread! Make sure that Host handles it properly! - virtual void BootDone() { - g_symbolMap->SortSymbols(); - mainWindow->Notify(MainWindowMsg::BOOT_DONE); - } - - virtual bool IsDebuggingEnabled() { -#ifdef _DEBUG - return true; -#else - return false; -#endif - } - virtual bool AttemptLoadSymbolMap() { - return false; - // TODO: Make this work with Qt and threaded GL... not sure what's so broken. - // auto fn = SymbolMapFilename(PSP_CoreParameter().fileToStart); - // return g_symbolMap->LoadSymbolMap(fn); - } - virtual void PrepareShutdown() { - g_symbolMap->SaveSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart)); - } - virtual void ResetSymbolMap() {} - virtual void AddSymbol(std::string name, u32 addr, u32 size, int type=0) {} - virtual void SetWindowTitle(const char *message) { - QString title = "PPSSPP " + QString(PPSSPP_GIT_VERSION) + " - " + QString::fromUtf8(message); - - mainWindow->setWindowTitle(title); - } - - void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override { - osm.Show(message, duration, color, -1, true, id); - } - - void SendUIMessage(const std::string &message, const std::string &value) override { - NativeMessageReceived(message.c_str(), value.c_str()); - } - - bool GPUDebuggingActive() - { - auto dialogDisplayList = mainWindow->GetDialogDisplaylist(); - if (dialogDisplayList && dialogDisplayList->isVisible()) - { - if (m_GPUStep && m_GPUFlag == -1) - m_GPUFlag = 0; - - return true; - } - return false; - } - void SetGPUStep(bool value, int flag = 0, u32 data = 0) - { - m_GPUStep = value; - m_GPUFlag = flag; - m_GPUData = data; - } -private: - MainWindow* mainWindow; - bool m_GPUStep; - int m_GPUFlag; - u32 m_GPUData; -}; -#endif diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index cbfceed7c2..9d50409539 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -101,6 +101,10 @@ #include "Common/KeyMap.h" #endif +#if !defined(MOBILE_DEVICE) && defined(USING_QT_UI) +#include "Qt/QtHost.h" +#endif + // The new UI framework, for initialization static UI::Theme ui_theme; From 80df926265519bb688ac1252e9a4fbf4ac400f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 3 Mar 2018 08:52:39 +0100 Subject: [PATCH 215/291] Qt: Set window title asynchronously. Should fix #10674 --- Qt/QtHost.h | 10 +++++++--- Qt/mainwindow.cpp | 4 ++++ Qt/mainwindow.h | 12 +++++++++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Qt/QtHost.h b/Qt/QtHost.h index 029c0b8987..2df6155bb0 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -82,9 +82,13 @@ public: g_symbolMap->SaveSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart)); } void SetWindowTitle(const char *message) override { - QString title = "PPSSPP " + QString(PPSSPP_GIT_VERSION) + " - " + QString::fromUtf8(message); - - mainWindow->setWindowTitle(title); + std::string title = std::string("PPSSPP ") + PPSSPP_GIT_VERSION; + if (message) + title += std::string(" - ") + message; +#ifdef _DEBUG + title += " (debug)"; +#endif + mainWindow->SetWindowTitleAsync(title); } void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override { diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index c9469c971e..116b7f084a 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -81,6 +81,10 @@ void MainWindow::newFrame() case MainWindowMsg::BOOT_DONE: bootDone(); break; + case MainWindowMsg::WINDOW_TITLE_CHANGED: + std::unique_lock lock(titleMutex_); + setWindowTitle(QString::fromUtf8(newWindowTitle_.c_str())); + break; } } } diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index 3e9c5469e8..ba2d3ff7dc 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -25,7 +25,8 @@ class MenuTree; // hacky, should probably use qt signals or something, but whatever.. enum class MainWindowMsg { - BOOT_DONE + BOOT_DONE, + WINDOW_TITLE_CHANGED, }; class MainWindow : public QMainWindow @@ -50,6 +51,12 @@ public: msgQueue_.push(msg); } + void SetWindowTitleAsync(std::string title) { + std::unique_lock lock(titleMutex_); + newWindowTitle_ = title; + Notify(MainWindowMsg::WINDOW_TITLE_CHANGED); + } + protected: void changeEvent(QEvent *e) { @@ -170,6 +177,9 @@ private: std::queue msgQueue_; std::mutex msgMutex_; + + std::string newWindowTitle_; + std::mutex titleMutex_; }; class MenuAction : public QAction From 1b8e3edb86e569ed14159e18cf1ca3dd82582b66 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Mar 2018 10:00:45 -0800 Subject: [PATCH 216/291] GLES: Buffer handling cleanup. Trying to fix the mystery issues on some devices. --- ext/native/thin3d/GLRenderManager.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index efab8bf3fd..504bc9f2ca 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -538,11 +538,12 @@ void GLPushBuffer::Map() { assert(!writePtr_); auto &info = buffers_[buf_]; writePtr_ = info.deviceMemory ? info.deviceMemory : info.localMemory; + info.flushOffset = 0; // Force alignment. This is needed for PushAligned() to work as expected. while ((intptr_t)writePtr_ & 15) { writePtr_++; + info.flushOffset++; } - info.flushOffset = 0; assert(writePtr_); } @@ -564,8 +565,10 @@ void GLPushBuffer::Flush() { buffers_[buf_].flushOffset = offset_; if (!buffers_[buf_].deviceMemory && writePtr_) { auto &info = buffers_[buf_]; - glBindBuffer(target_, info.buffer->buffer); - glBufferSubData(target_, 0, info.flushOffset, info.localMemory); + if (info.flushOffset != 0) { + glBindBuffer(target_, info.buffer->buffer); + glBufferSubData(target_, 0, info.flushOffset, info.localMemory); + } // Here we will submit all the draw calls, with the already known buffer and offsets. // Might as well reset the write pointer here and start over the current buffer. @@ -660,6 +663,7 @@ size_t GLPushBuffer::GetTotalSize() const { } void GLPushBuffer::MapDevice() { + bool mapChanged = false; for (auto &info : buffers_) { if (!info.buffer->buffer) { // Can't map - no device buffer associated yet. @@ -669,16 +673,18 @@ void GLPushBuffer::MapDevice() { assert(!info.deviceMemory); // TODO: Can we use GL_WRITE_ONLY? info.deviceMemory = (uint8_t *)info.buffer->Map(GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); + mapChanged = mapChanged || info.deviceMemory != nullptr; if (!info.deviceMemory && !info.localMemory) { // Somehow it failed, let's dodge crashing. info.localMemory = new uint8_t[info.buffer->size_]; + mapChanged = true; } assert(info.localMemory || info.deviceMemory); } - if (writePtr_) { + if (writePtr_ && mapChanged) { // This can happen during a sync. Remap. writePtr_ = nullptr; Map(); From 38bf10baaabe4e89586d588b9a41e276748fe0d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 4 Mar 2018 22:21:57 +0100 Subject: [PATCH 217/291] GL: Use AllocateAlignedMemory to make sure localMemory is always aligned. Fixes #10666 Seems the code that tries to align is faulty in some cases but this avoids the issue at least. --- ext/native/thin3d/GLRenderManager.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 504bc9f2ca..62dbc1e60d 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -5,6 +5,7 @@ #include "thread/threadutil.h" #include "base/logging.h" #include "GPU/GPUState.h" +#include "Common/MemoryUtil.h" #if 0 // def _DEBUG #define VLOG ILOG @@ -592,7 +593,7 @@ void GLPushBuffer::Flush() { bool GLPushBuffer::AddBuffer() { BufInfo info; - info.localMemory = new uint8_t[size_]; + info.localMemory = (uint8_t *)AllocateAlignedMemory(size_, 16); info.buffer = render_->CreateBuffer(target_, size_, GL_DYNAMIC_DRAW); buf_ = buffers_.size(); buffers_.push_back(info); @@ -603,7 +604,7 @@ void GLPushBuffer::Destroy() { for (BufInfo &info : buffers_) { // This will automatically unmap device memory, if needed. render_->DeleteBuffer(info.buffer); - delete[] info.localMemory; + FreeAlignedMemory(info.localMemory); } buffers_.clear(); } @@ -637,7 +638,7 @@ void GLPushBuffer::Defragment() { // Let's take this chance to jetison localMemory we don't need. for (auto &info : buffers_) { if (info.deviceMemory) { - delete[] info.localMemory; + FreeAlignedMemory(info.localMemory); info.localMemory = nullptr; } } @@ -677,7 +678,7 @@ void GLPushBuffer::MapDevice() { if (!info.deviceMemory && !info.localMemory) { // Somehow it failed, let's dodge crashing. - info.localMemory = new uint8_t[info.buffer->size_]; + info.localMemory = (uint8_t *)AllocateAlignedMemory(info.buffer->size_, 16); mapChanged = true; } From 021ade506594942f4babfc737e7699e0b2c10dc9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Mar 2018 13:26:52 -0800 Subject: [PATCH 218/291] GLES: Fix force alignment on buffer map. --- ext/native/thin3d/GLRenderManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 62dbc1e60d..f1f6b87ba0 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -543,6 +543,7 @@ void GLPushBuffer::Map() { // Force alignment. This is needed for PushAligned() to work as expected. while ((intptr_t)writePtr_ & 15) { writePtr_++; + offset_++; info.flushOffset++; } assert(writePtr_); From 7c983a6842bcebdec7f83a9d8fe88d90b47f33ff Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Mar 2018 14:23:09 -0800 Subject: [PATCH 219/291] GLES: Support more buffer mapping strategies. --- ext/native/thin3d/GLRenderManager.cpp | 67 ++++++++++++++++++++------- ext/native/thin3d/GLRenderManager.h | 26 ++++++++++- 2 files changed, 74 insertions(+), 19 deletions(-) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index f1f6b87ba0..e126fd34e8 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -59,6 +59,33 @@ GLRenderManager::~GLRenderManager() { void GLRenderManager::ThreadStart() { queueRunner_.CreateDeviceObjects(); threadFrame_ = threadInitFrame_; + + bool mapBuffers = (gl_extensions.bugs & BUG_ANY_MAP_BUFFER_RANGE_SLOW) == 0; + bool hasBufferStorage = gl_extensions.ARB_buffer_storage || gl_extensions.EXT_buffer_storage; + if (!gl_extensions.VersionGEThan(3, 0, 0) && gl_extensions.IsGLES && !hasBufferStorage) { + // Force disable if it wouldn't work anyway. + mapBuffers = false; + } + + // Notes on buffer mapping: + // NVIDIA GTX 9xx / 2017-10 drivers - mapping improves speed, basic unmap seems best. + // PowerVR GX6xxx / iOS 10.3 - mapping has little improvement, explicit flush is slower. + if (mapBuffers) { + switch (gl_extensions.gpuVendor) { + case GPU_VENDOR_NVIDIA: + bufferStrategy_ = GLBufferStrategy::FRAME_UNMAP; + break; + + case GPU_VENDOR_QUALCOMM: + bufferStrategy_ = GLBufferStrategy::FLUSH_INVALIDATE_UNMAP; + break; + + default: + bufferStrategy_ = GLBufferStrategy::SUBDATA; + } + } else { + bufferStrategy_ = GLBufferStrategy::SUBDATA; + } } void GLRenderManager::ThreadEnd() { @@ -436,7 +463,7 @@ void GLRenderManager::Run(int frame) { initStepsOnThread.clear(); for (auto iter : frameData.activePushBuffers) { - iter->MapDevice(); + iter->MapDevice(bufferStrategy_); } switch (frameData.type) { @@ -580,7 +607,7 @@ void GLPushBuffer::Flush() { } // For device memory, we flush all buffers here. - if (gl_extensions.VersionGEThan(3, 0, 0)) { + if ((strategy_ & GLBufferStrategy::MASK_FLUSH) != 0) { for (auto &info : buffers_) { if (info.flushOffset == 0 || !info.deviceMemory) continue; @@ -664,17 +691,20 @@ size_t GLPushBuffer::GetTotalSize() const { return sum; } -void GLPushBuffer::MapDevice() { +void GLPushBuffer::MapDevice(GLBufferStrategy strategy) { + strategy_ = strategy; + if (strategy_ == GLBufferStrategy::SUBDATA) { + return; + } + bool mapChanged = false; for (auto &info : buffers_) { - if (!info.buffer->buffer) { - // Can't map - no device buffer associated yet. + if (!info.buffer->buffer || info.deviceMemory) { + // Can't map - no device buffer associated yet or already mapped. continue; } - assert(!info.deviceMemory); - // TODO: Can we use GL_WRITE_ONLY? - info.deviceMemory = (uint8_t *)info.buffer->Map(GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); + info.deviceMemory = (uint8_t *)info.buffer->Map(strategy_); mapChanged = mapChanged || info.deviceMemory != nullptr; if (!info.deviceMemory && !info.localMemory) { @@ -703,27 +733,30 @@ void GLPushBuffer::UnmapDevice() { } } -void *GLRBuffer::Map(GLbitfield access) { +void *GLRBuffer::Map(GLBufferStrategy strategy) { assert(buffer != 0); - // Notes on buffer mapping: - // NVIDIA GTX 9xx / 2017-10 drivers - mapping improves speed, explicit flush zero cost/benefit. - // PowerVR GX6xxx / iOS 10.3 - mapping has little improvement, explicit flush is slower. - // AMD / unknown - mapping causes black screens and flickering? - // Mali / unknown - mapping causes black screens and flickering? + GLbitfield access = GL_MAP_WRITE_BIT; + if ((strategy & GLBufferStrategy::MASK_FLUSH) != 0) { + access |= GL_MAP_FLUSH_EXPLICIT_BIT; + } + if ((strategy & GLBufferStrategy::MASK_INVALIDATE) != 0) { + access |= GL_MAP_INVALIDATE_BUFFER_BIT; + } void *p = nullptr; - bool allowNativeBuffer = (gl_extensions.bugs & BUG_ANY_MAP_BUFFER_RANGE_SLOW) == 0; + bool allowNativeBuffer = strategy != GLBufferStrategy::SUBDATA; if (allowNativeBuffer) { glBindBuffer(target_, buffer); if (gl_extensions.ARB_buffer_storage || gl_extensions.EXT_buffer_storage) { #ifndef IOS if (!hasStorage_) { + GLbitfield storageFlags = access & ~(GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); #ifdef USING_GLES2 - glBufferStorageEXT(target_, size_, nullptr, access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); + glBufferStorageEXT(target_, size_, nullptr, storageFlags); #else - glBufferStorage(target_, size_, nullptr, access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); + glBufferStorage(target_, size_, nullptr, storageFlags); #endif hasStorage_ = true; } diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index f9b30936fb..11b93dafd9 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -130,6 +130,26 @@ public: std::unordered_map uniformCache_; }; +enum class GLBufferStrategy { + SUBDATA = 0, + + MASK_FLUSH = 0x10, + MASK_INVALIDATE = 0x20, + + // Map/unmap the buffer each frame. + FRAME_UNMAP = 1, + // Map/unmap and also invalidate the buffer on map. + INVALIDATE_UNMAP = MASK_INVALIDATE, + // Map/unmap and explicitly flushed changed ranges. + FLUSH_UNMAP = MASK_FLUSH, + // Map/unmap, invalidate on map, and explicit flush. + FLUSH_INVALIDATE_UNMAP = MASK_FLUSH | MASK_INVALIDATE, +}; + +static inline int operator &(const GLBufferStrategy &lhs, const GLBufferStrategy &rhs) { + return (int)lhs & (int)rhs; +} + class GLRBuffer { public: GLRBuffer(GLuint target, size_t size) : target_(target), size_((int)size) {} @@ -139,7 +159,7 @@ public: } } - void *Map(GLbitfield access); + void *Map(GLBufferStrategy strategy); bool Unmap(); bool Mapped() { @@ -745,6 +765,7 @@ private: int curFrame_ = 0; std::function swapFunction_; + GLBufferStrategy bufferStrategy_ = GLBufferStrategy::SUBDATA; int targetWidth_ = 0; int targetHeight_ = 0; @@ -849,7 +870,7 @@ public: void Flush(); protected: - void MapDevice(); + void MapDevice(GLBufferStrategy strategy); void UnmapDevice(); private: @@ -864,6 +885,7 @@ private: size_t size_ = 0; uint8_t *writePtr_ = nullptr; GLuint target_; + GLBufferStrategy strategy_ = GLBufferStrategy::SUBDATA; friend class GLRenderManager; }; From d3665a848238dcf9d3636e8d991d9349b451faf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 2 Mar 2018 12:10:32 +0100 Subject: [PATCH 220/291] Minor cleanup --- GPU/Common/DrawEngineCommon.cpp | 21 ++++++++------------- GPU/Common/DrawEngineCommon.h | 2 -- GPU/GPUCommon.cpp | 7 +------ 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 166cd9a659..a3746d0874 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -50,18 +50,6 @@ DrawEngineCommon::~DrawEngineCommon() { }); } -void DrawEngineCommon::SetupVertexDecoder(u32 vertType) { - // As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it - // into the top of the verttype where there are unused bits. - const u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24); - - // If vtype has changed, setup the vertex decoder. - if (vertTypeID != lastVType_) { - dec_ = GetVertexDecoder(vertTypeID); - lastVType_ = vertTypeID; - } -} - VertexDecoder *DrawEngineCommon::GetVertexDecoder(u32 vtype) { VertexDecoder *dec = decoderMap_.Get(vtype); if (dec) @@ -682,7 +670,14 @@ void DrawEngineCommon::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, prevPrim_ = prim; } - SetupVertexDecoder(vertType); + // As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it + // into the top of the verttype where there are unused bits. + const u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24); + // If vtype has changed, setup the vertex decoder. + if (vertTypeID != lastVType_) { + dec_ = GetVertexDecoder(vertTypeID); + lastVType_ = vertTypeID; + } *bytesRead = vertexCount * dec_->VertexSize(); if ((vertexCount < 2 && prim > 0) || (vertexCount < 3 && prim > 2 && prim != GE_PRIM_RECTANGLES)) diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 64ef9ae9dc..c4af21114b 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -74,8 +74,6 @@ public: virtual void Resized(); - void SetupVertexDecoder(u32 vertType); - bool IsCodePtrVertexDecoder(const u8 *ptr) const { return decJitCache_->IsInSpace(ptr); } diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 19524f0f6b..a5764e7a18 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1491,8 +1491,7 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { - drawEngineCommon_->SetupVertexDecoder(gstate.vertType); // Do we still need to do this? - // Rough estimate, not sure what's correct. + // Rough estimate, not sure what's correct. cyclesExecuted += EstimatePerVertexCost() * count; return; } @@ -1560,10 +1559,6 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { } GEPrimitiveType newPrim = static_cast((data >> 16) & 7); - // Can be more lenient later. - if (newPrim != prim) { - goto bail; - } // TODO: more efficient updating of verts/inds verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); inds = 0; From 45cfda4aa028b12f9079f9f1fdc29f7c6666313d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 2 Mar 2018 13:03:16 +0100 Subject: [PATCH 221/291] Small refactoring in VertexDecoderCommon --- GPU/Common/VertexDecoderCommon.cpp | 64 ++++++++++++------------------ GPU/Common/VertexDecoderCommon.h | 2 + GPU/Math3D.h | 2 +- 3 files changed, 28 insertions(+), 40 deletions(-) diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index dccd4dccf9..a71125aabc 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -219,52 +219,37 @@ void VertexDecoder::Step_WeightsFloat() const wt[j++] = 0.0f; } -void VertexDecoder::Step_WeightsU8Skin() const -{ +void VertexDecoder::ComputeSkinMatrix(const float weights[8]) const { memset(skinMatrix, 0, sizeof(skinMatrix)); + for (int j = 0; j < nweights; j++) { + const float *bone = &gstate.boneMatrix[j * 12]; + if (weights[j] != 0.0f) { + for (int i = 0; i < 12; i++) { + skinMatrix[i] += weights[j] * bone[i]; + } + } + } +} + +void VertexDecoder::Step_WeightsU8Skin() const { const u8 *wdata = (const u8*)(ptr_); - for (int j = 0; j < nweights; j++) { - const float *bone = &gstate.boneMatrix[j * 12]; - if (wdata[j] != 0) { - float weight = wdata[j] * (1.0f / 128.0f); - for (int i = 0; i < 12; i++) { - skinMatrix[i] += weight * bone[i]; - } - } - } + float weights[8]; + for (int j = 0; j < nweights; j++) + weights[j] = wdata[j] * (1.0f / 128.0f); + ComputeSkinMatrix(weights); } -void VertexDecoder::Step_WeightsU16Skin() const -{ - memset(skinMatrix, 0, sizeof(skinMatrix)); +void VertexDecoder::Step_WeightsU16Skin() const { const u16 *wdata = (const u16*)(ptr_); - for (int j = 0; j < nweights; j++) { - const float *bone = &gstate.boneMatrix[j * 12]; - if (wdata[j] != 0) { - float weight = wdata[j] * (1.0f / 32768.0f); - for (int i = 0; i < 12; i++) { - skinMatrix[i] += weight * bone[i]; - } - } - } + float weights[8]; + for (int j = 0; j < nweights; j++) + weights[j] = wdata[j] * (1.0f / 32768.0f); + ComputeSkinMatrix(weights); } -// Float weights should be uncommon, we can live with having to multiply these by 2.0 -// to avoid special checks in the vertex shader generator. -// (PSP uses 0.0-2.0 fixed point numbers for weights) -void VertexDecoder::Step_WeightsFloatSkin() const -{ - memset(skinMatrix, 0, sizeof(skinMatrix)); +void VertexDecoder::Step_WeightsFloatSkin() const { const float *wdata = (const float*)(ptr_); - for (int j = 0; j < nweights; j++) { - const float *bone = &gstate.boneMatrix[j * 12]; - float weight = wdata[j]; - if (weight > 0.0) { - for (int i = 0; i < 12; i++) { - skinMatrix[i] += weight * bone[i]; - } - } - } + ComputeSkinMatrix(wdata); } void VertexDecoder::Step_TcU8ToFloat() const @@ -1000,8 +985,9 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, biggest = wtalign[weighttype]; if (skinInDecode) { + // No visible output, computes a matrix that is passed through the skinMatrix variable + // to the "nrm" and "pos" steps. steps_[numSteps_++] = wtstep_skin[weighttype]; - // No visible output, passed in register/external memory to the "pos" step. } else { int fmtBase = DEC_FLOAT_1; if (options.expandAllWeightsToFloat) { diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 2066defced..81cb134bdc 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -466,6 +466,8 @@ public: void Step_WeightsU16ToFloat() const; void Step_WeightsFloat() const; + void ComputeSkinMatrix(const float weights[8]) const; + void Step_WeightsU8Skin() const; void Step_WeightsU16Skin() const; void Step_WeightsFloatSkin() const; diff --git a/GPU/Math3D.h b/GPU/Math3D.h index 081701da6f..ba01d31600 100644 --- a/GPU/Math3D.h +++ b/GPU/Math3D.h @@ -821,7 +821,7 @@ typedef Math3D::Vec3 Vec3f; typedef Math3D::Vec3Packed Vec3Packedf; typedef Math3D::Vec4 Vec4f; - +// v and vecOut must point to different memory. inline void Vec3ByMatrix43(float vecOut[3], const float v[3], const float m[12]) { vecOut[0] = v[0] * m[0] + v[1] * m[3] + v[2] * m[6] + m[9]; vecOut[1] = v[0] * m[1] + v[1] * m[4] + v[2] * m[7] + m[10]; From 66cbad443afd475f15fcb8dbe5b92dd7cf26d6ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 2 Mar 2018 13:16:03 +0100 Subject: [PATCH 222/291] Add necessary decode functions to support morph+skin --- GPU/Common/VertexDecoderCommon.cpp | 94 +++++++++++++++++++++++++++++- GPU/Common/VertexDecoderCommon.h | 8 +++ 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index a71125aabc..e29d4aa7c0 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -673,6 +673,42 @@ void VertexDecoder::Step_NormalFloatMorph() const } } +void VertexDecoder::Step_NormalS8MorphSkin() const { + float *normal = (float *)(decoded_ + decFmt.nrmoff); + float nrm[3]{}; + for (int n = 0; n < morphcount; n++) { + const s8 *bv = (const s8*)(ptr_ + onesize_ * n + nrmoff); + const float multiplier = gstate_c.morphWeights[n] * (1.0f / 128.0f); + for (int j = 0; j < 3; j++) + normal[j] += bv[j] * multiplier; + } + Norm3ByMatrix43(normal, nrm, skinMatrix); +} + +void VertexDecoder::Step_NormalS16MorphSkin() const { + float *normal = (float *)(decoded_ + decFmt.nrmoff); + float nrm[3]{}; + for (int n = 0; n < morphcount; n++) { + const s16 *sv = (const s16_le *)(ptr_ + onesize_ * n + nrmoff); + const float multiplier = gstate_c.morphWeights[n] * (1.0f / 32768.0f); + for (int j = 0; j < 3; j++) + nrm[j] += sv[j] * multiplier; + } + Norm3ByMatrix43(normal, nrm, skinMatrix); +} + +void VertexDecoder::Step_NormalFloatMorphSkin() const { + float *normal = (float *)(decoded_ + decFmt.nrmoff); + float nrm[3]{}; + for (int n = 0; n < morphcount; n++) { + float multiplier = gstate_c.morphWeights[n]; + const float *fv = (const float*)(ptr_ + onesize_ * n + nrmoff); + for (int j = 0; j < 3; j++) + nrm[j] += fv[j] * multiplier; + } + Norm3ByMatrix43(normal, nrm, skinMatrix); +} + void VertexDecoder::Step_PosS8() const { float *pos = (float *)(decoded_ + decFmt.posoff); @@ -780,6 +816,41 @@ void VertexDecoder::Step_PosFloatMorph() const } } +void VertexDecoder::Step_PosS8MorphSkin() const { + float *v = (float *)(decoded_ + decFmt.posoff); + float pos[3]{}; + for (int n = 0; n < morphcount; n++) { + const float multiplier = 1.0f / 128.0f; + const s8 *sv = (const s8*)(ptr_ + onesize_ * n + posoff); + for (int j = 0; j < 3; j++) + pos[j] += (float)sv[j] * (multiplier * gstate_c.morphWeights[n]); + } + Vec3ByMatrix43(v, pos, skinMatrix); +} + +void VertexDecoder::Step_PosS16MorphSkin() const { + float *v = (float *)(decoded_ + decFmt.posoff); + float pos[3]{}; + for (int n = 0; n < morphcount; n++) { + const float multiplier = 1.0f / 32768.0f; + const s16 *sv = (const s16*)(ptr_ + onesize_ * n + posoff); + for (int j = 0; j < 3; j++) + pos[j] += (float)sv[j] * (multiplier * gstate_c.morphWeights[n]); + } + Vec3ByMatrix43(v, pos, skinMatrix); +} + +void VertexDecoder::Step_PosFloatMorphSkin() const { + float *v = (float *)(decoded_ + decFmt.posoff); + float pos[3]{}; + for (int n = 0; n < morphcount; n++) { + const float *fv = (const float*)(ptr_ + onesize_ * n + posoff); + for (int j = 0; j < 3; j++) + pos[j] += fv[j] * gstate_c.morphWeights[n]; + } + Vec3ByMatrix43(v, pos, skinMatrix); +} + static const StepFunction wtstep[4] = { 0, &VertexDecoder::Step_WeightsU8, @@ -794,6 +865,9 @@ static const StepFunction wtstepToFloat[4] = { &VertexDecoder::Step_WeightsFloat, }; +// TODO: Morph weights correctly! This is missing. Not sure if any game actually +// use this functionality at all. + static const StepFunction wtstep_skin[4] = { 0, &VertexDecoder::Step_WeightsU8Skin, @@ -921,6 +995,13 @@ static const StepFunction nrmstep_morph[4] = { &VertexDecoder::Step_NormalFloatMorph, }; +static const StepFunction nrmstep_morphskin[4] = { + 0, + &VertexDecoder::Step_NormalS8MorphSkin, + &VertexDecoder::Step_NormalS16MorphSkin, + &VertexDecoder::Step_NormalFloatMorphSkin, +}; + static const StepFunction posstep[4] = { &VertexDecoder::Step_PosS8, &VertexDecoder::Step_PosS8, @@ -942,6 +1023,13 @@ static const StepFunction posstep_morph[4] = { &VertexDecoder::Step_PosFloatMorph, }; +static const StepFunction posstep_morph_skin[4] = { + &VertexDecoder::Step_PosS8MorphSkin, + &VertexDecoder::Step_PosS8MorphSkin, + &VertexDecoder::Step_PosS16MorphSkin, + &VertexDecoder::Step_PosFloatMorphSkin, +}; + static const StepFunction posstep_through[4] = { &VertexDecoder::Step_PosS8Through, &VertexDecoder::Step_PosS8Through, @@ -987,6 +1075,8 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, if (skinInDecode) { // No visible output, computes a matrix that is passed through the skinMatrix variable // to the "nrm" and "pos" steps. + // Technically we should support morphing the weights too, but I have a hard time + // imagining that any game would use that.. but you never know. steps_[numSteps_++] = wtstep_skin[weighttype]; } else { int fmtBase = DEC_FLOAT_1; @@ -1077,7 +1167,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, biggest = nrmalign[nrm]; if (skinInDecode) { - steps_[numSteps_++] = nrmstep_skin[nrm]; + steps_[numSteps_++] = morphcount == 1 ? nrmstep_skin[nrm] : nrmstep_morphskin[nrm]; // After skinning, we always have three floats. decFmt.nrmfmt = DEC_FLOAT_3; } else { @@ -1128,7 +1218,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, decFmt.posfmt = DEC_FLOAT_3; } else { if (skinInDecode) { - steps_[numSteps_++] = posstep_skin[pos]; + steps_[numSteps_++] = morphcount == 1 ? posstep_skin[pos] : posstep_morph_skin[pos]; decFmt.posfmt = DEC_FLOAT_3; } else { steps_[numSteps_++] = morphcount == 1 ? posstep[pos] : posstep_morph[pos]; diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 81cb134bdc..cabfc5138d 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -519,6 +519,10 @@ public: void Step_NormalS16Morph() const; void Step_NormalFloatMorph() const; + void Step_NormalS8MorphSkin() const; + void Step_NormalS16MorphSkin() const; + void Step_NormalFloatMorphSkin() const; + void Step_PosS8() const; void Step_PosS16() const; void Step_PosFloat() const; @@ -531,6 +535,10 @@ public: void Step_PosS16Morph() const; void Step_PosFloatMorph() const; + void Step_PosS8MorphSkin() const; + void Step_PosS16MorphSkin() const; + void Step_PosFloatMorphSkin() const; + void Step_PosS8Through() const; void Step_PosS16Through() const; void Step_PosFloatThrough() const; From 978f8e73e58ddb358a161fde3bded8ff8006b037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 2 Mar 2018 13:59:11 +0100 Subject: [PATCH 223/291] Remove checks that disabled software skinning if there was morph. --- GPU/GPUCommon.cpp | 14 +++++++------- GPU/GPUState.cpp | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index a5764e7a18..7640b7e794 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1441,8 +1441,8 @@ void GPUCommon::Execute_LoadClut(u32 op, u32 diff) { } void GPUCommon::Execute_VertexTypeSkinning(u32 op, u32 diff) { - // Don't flush when weight count changes, unless morph is enabled. - if ((diff & ~GE_VTYPE_WEIGHTCOUNT_MASK) || (op & GE_VTYPE_MORPHCOUNT_MASK) != 0) { + // Don't flush when weight count changes. + if (diff & ~GE_VTYPE_WEIGHTCOUNT_MASK) { // Restore and flush gstate.vertType ^= diff; Flush(); @@ -1638,7 +1638,7 @@ void GPUCommon::Execute_Bezier(u32 op, u32 diff) { indices = Memory::GetPointerUnchecked(gstate_c.indexAddr); } - if ((gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) || vertTypeIsSkinningEnabled(gstate.vertType)) { + if (vertTypeIsSkinningEnabled(gstate.vertType)) { DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); } @@ -1700,7 +1700,7 @@ void GPUCommon::Execute_Spline(u32 op, u32 diff) { indices = Memory::GetPointerUnchecked(gstate_c.indexAddr); } - if ((gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) || vertTypeIsSkinningEnabled(gstate.vertType)) { + if (vertTypeIsSkinningEnabled(gstate.vertType)) { DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); } @@ -1985,7 +1985,7 @@ void GPUCommon::Execute_BoneMtxNum(u32 op, u32 diff) { if (fastLoad) { // If we can't use software skinning, we have to flush and dirty. - if (!g_Config.bSoftwareSkinning || (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) != 0) { + if (!g_Config.bSoftwareSkinning) { while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) { const u32 newVal = src[i] << 8; if (dst[i] != newVal) { @@ -2030,7 +2030,7 @@ void GPUCommon::Execute_BoneMtxData(u32 op, u32 diff) { u32 newVal = op << 8; if (num < 96 && newVal != ((const u32 *)gstate.boneMatrix)[num]) { // Bone matrices should NOT flush when software skinning is enabled! - if (!g_Config.bSoftwareSkinning || (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) != 0) { + if (!g_Config.bSoftwareSkinning) { Flush(); gstate_c.Dirty(DIRTY_BONEMATRIX0 << (num / 12)); } else { @@ -2180,7 +2180,7 @@ void GPUCommon::FastLoadBoneMatrix(u32 target) { uniformsToDirty |= DIRTY_BONEMATRIX0 << ((mtxNum + 1) & 7); } - if (!g_Config.bSoftwareSkinning || (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) != 0) { + if (!g_Config.bSoftwareSkinning) { Flush(); gstate_c.Dirty(uniformsToDirty); } else { diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 38a823174a..7e3f3812ef 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -241,7 +241,7 @@ void GPUgstate::Restore(u32_le *ptr) { } bool vertTypeIsSkinningEnabled(u32 vertType) { - if (g_Config.bSoftwareSkinning && ((vertType & GE_VTYPE_MORPHCOUNT_MASK) == 0)) + if (g_Config.bSoftwareSkinning) return false; else return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE); From dcb773d62436525b4719555ce23a38a1342b45f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 2 Mar 2018 13:21:47 +0100 Subject: [PATCH 224/291] Start removing support for hardware skinning. --- GPU/Common/VertexDecoderCommon.cpp | 48 +++++------------------------- 1 file changed, 8 insertions(+), 40 deletions(-) diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index e29d4aa7c0..53c327e19b 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -1063,7 +1063,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, DEBUG_LOG(G3D, "VTYPE: THRU=%i TC=%i COL=%i POS=%i NRM=%i WT=%i NW=%i IDX=%i MC=%i", (int)throughmode, tc, col, pos, nrm, weighttype, nweights, idx, morphcount); } - bool skinInDecode = weighttype != 0 && g_Config.bSoftwareSkinning && morphcount == 1; + bool skinning = weighttype != 0; if (weighttype) { // && nweights? weightoff = size; @@ -1072,43 +1072,11 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, if (wtalign[weighttype] > biggest) biggest = wtalign[weighttype]; - if (skinInDecode) { - // No visible output, computes a matrix that is passed through the skinMatrix variable - // to the "nrm" and "pos" steps. - // Technically we should support morphing the weights too, but I have a hard time - // imagining that any game would use that.. but you never know. - steps_[numSteps_++] = wtstep_skin[weighttype]; - } else { - int fmtBase = DEC_FLOAT_1; - if (options.expandAllWeightsToFloat) { - steps_[numSteps_++] = wtstepToFloat[weighttype]; - fmtBase = DEC_FLOAT_1; - } else { - steps_[numSteps_++] = wtstep[weighttype]; - if (weighttype == GE_VTYPE_WEIGHT_8BIT >> GE_VTYPE_WEIGHT_SHIFT) { - fmtBase = DEC_U8_1; - } else if (weighttype == GE_VTYPE_WEIGHT_16BIT >> GE_VTYPE_WEIGHT_SHIFT) { - fmtBase = DEC_U16_1; - } else if (weighttype == GE_VTYPE_WEIGHT_FLOAT >> GE_VTYPE_WEIGHT_SHIFT) { - fmtBase = DEC_FLOAT_1; - } - } - - int numWeights = TranslateNumBones(nweights); - - if (numWeights <= 4) { - decFmt.w0off = decOff; - decFmt.w0fmt = fmtBase + numWeights - 1; - decOff += DecFmtSize(decFmt.w0fmt); - } else { - decFmt.w0off = decOff; - decFmt.w0fmt = fmtBase + 3; - decOff += DecFmtSize(decFmt.w0fmt); - decFmt.w1off = decOff; - decFmt.w1fmt = fmtBase + numWeights - 5; - decOff += DecFmtSize(decFmt.w1fmt); - } - } + // No visible output, computes a matrix that is passed through the skinMatrix variable + // to the "nrm" and "pos" steps. + // Technically we should support morphing the weights too, but I have a hard time + // imagining that any game would use that.. but you never know. + steps_[numSteps_++] = wtstep_skin[weighttype]; } if (tc) { @@ -1166,7 +1134,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, if (nrmalign[nrm] > biggest) biggest = nrmalign[nrm]; - if (skinInDecode) { + if (skinning) { steps_[numSteps_++] = morphcount == 1 ? nrmstep_skin[nrm] : nrmstep_morphskin[nrm]; // After skinning, we always have three floats. decFmt.nrmfmt = DEC_FLOAT_3; @@ -1217,7 +1185,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, steps_[numSteps_++] = posstep_through[pos]; decFmt.posfmt = DEC_FLOAT_3; } else { - if (skinInDecode) { + if (skinning) { steps_[numSteps_++] = morphcount == 1 ? posstep_skin[pos] : posstep_morph_skin[pos]; decFmt.posfmt = DEC_FLOAT_3; } else { From 44100c6c1d38bf2318b157cd28a1cbf7aab5270d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 2 Mar 2018 13:26:32 +0100 Subject: [PATCH 225/291] VertexLoader: Remove now-unused weights translation code --- GPU/Common/VertexDecoderArm.cpp | 52 --------- GPU/Common/VertexDecoderArm64.cpp | 41 ------- GPU/Common/VertexDecoderCommon.cpp | 75 ------------- GPU/Common/VertexDecoderCommon.h | 12 -- GPU/Common/VertexDecoderX86.cpp | 175 ----------------------------- 5 files changed, 355 deletions(-) diff --git a/GPU/Common/VertexDecoderArm.cpp b/GPU/Common/VertexDecoderArm.cpp index 1f7d65a833..79e6584ae2 100644 --- a/GPU/Common/VertexDecoderArm.cpp +++ b/GPU/Common/VertexDecoderArm.cpp @@ -111,9 +111,6 @@ static const ARMReg srcNEON = Q2; static const ARMReg accNEON = Q3; static const JitLookup jitLookup[] = { - {&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8}, - {&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16}, - {&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat}, {&VertexDecoder::Step_WeightsU8Skin, &VertexDecoderJitCache::Jit_WeightsU8Skin}, {&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin}, {&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin}, @@ -326,55 +323,6 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int return (JittedVertexDecoder)start; } -void VertexDecoderJitCache::Jit_WeightsU8() { - // Basic implementation - a byte at a time. TODO: Optimize - int j; - for (j = 0; j < dec_->nweights; j++) { - LDRB(tempReg1, srcReg, dec_->weightoff + j); - STRB(tempReg1, dstReg, dec_->decFmt.w0off + j); - } - if (j & 3) { - // Create a zero register. Might want to make a fixed one. - EOR(scratchReg, scratchReg, scratchReg); - } - while (j & 3) { - STRB(scratchReg, dstReg, dec_->decFmt.w0off + j); - j++; - } -} - -void VertexDecoderJitCache::Jit_WeightsU16() { - // Basic implementation - a short at a time. TODO: Optimize - int j; - for (j = 0; j < dec_->nweights; j++) { - LDRH(tempReg1, srcReg, dec_->weightoff + j * 2); - STRH(tempReg1, dstReg, dec_->decFmt.w0off + j * 2); - } - if (j & 3) { - // Create a zero register. Might want to make a fixed one. - EOR(scratchReg, scratchReg, scratchReg); - } - while (j & 3) { - STRH(scratchReg, dstReg, dec_->decFmt.w0off + j * 2); - j++; - } -} - -void VertexDecoderJitCache::Jit_WeightsFloat() { - int j; - for (j = 0; j < dec_->nweights; j++) { - LDR(tempReg1, srcReg, dec_->weightoff + j * 4); - STR(tempReg1, dstReg, dec_->decFmt.w0off + j * 4); - } - if (j & 3) { - EOR(tempReg1, tempReg1, tempReg1); - } - while (j & 3) { // Zero additional weights rounding up to 4. - STR(tempReg1, dstReg, dec_->decFmt.w0off + j * 4); - j++; - } -} - static const ARMReg weightRegs[8] = { S8, S9, S10, S11, S12, S13, S14, S15 }; static const ARMReg neonWeightRegsD[4] = { D4, D5, D6, D7 }; static const ARMReg neonWeightRegsQ[2] = { Q2, Q3 }; diff --git a/GPU/Common/VertexDecoderArm64.cpp b/GPU/Common/VertexDecoderArm64.cpp index aab6b4ca36..acfa230ea9 100644 --- a/GPU/Common/VertexDecoderArm64.cpp +++ b/GPU/Common/VertexDecoderArm64.cpp @@ -85,9 +85,6 @@ static const ARM64Reg neonWeightRegsQ[2] = { Q3, Q2 }; // reverse order to prev // Q16+ are free-for-all for matrices. In 16 registers, we can fit 4 4x4 matrices. static const JitLookup jitLookup[] = { - {&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8}, - {&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16}, - {&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat}, {&VertexDecoder::Step_WeightsU8Skin, &VertexDecoderJitCache::Jit_WeightsU8Skin}, {&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin}, {&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin}, @@ -356,44 +353,6 @@ void VertexDecoderJitCache::Jit_ApplyWeights() { } } -void VertexDecoderJitCache::Jit_WeightsU8() { - // Basic implementation - a byte at a time. TODO: Optimize - int j; - for (j = 0; j < dec_->nweights; j++) { - LDRB(INDEX_UNSIGNED, tempReg1, srcReg, dec_->weightoff + j); - STRB(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.w0off + j); - } - while (j & 3) { - STRB(INDEX_UNSIGNED, WZR, dstReg, dec_->decFmt.w0off + j); - j++; - } -} - -void VertexDecoderJitCache::Jit_WeightsU16() { - // Basic implementation - a short at a time. TODO: Optimize - int j; - for (j = 0; j < dec_->nweights; j++) { - LDRH(INDEX_UNSIGNED, tempReg1, srcReg, dec_->weightoff + j * 2); - STRH(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.w0off + j * 2); - } - while (j & 3) { - STRH(INDEX_UNSIGNED, WZR, dstReg, dec_->decFmt.w0off + j * 2); - j++; - } -} - -void VertexDecoderJitCache::Jit_WeightsFloat() { - int j; - for (j = 0; j < dec_->nweights; j++) { - LDR(INDEX_UNSIGNED, tempReg1, srcReg, dec_->weightoff + j * 4); - STR(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.w0off + j * 4); - } - while (j & 3) { // Zero additional weights rounding up to 4. - STR(INDEX_UNSIGNED, WZR, dstReg, dec_->decFmt.w0off + j * 4); - j++; - } -} - void VertexDecoderJitCache::Jit_WeightsU8Skin() { // Weight is first so srcReg is correct. switch (dec_->nweights) { diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index 53c327e19b..af3f63d5a7 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -158,67 +158,6 @@ void PrintDecodedVertex(VertexReader &vtx) { VertexDecoder::VertexDecoder() : decoded_(nullptr), ptr_(nullptr), jitted_(0), jittedSize_(0) { } -void VertexDecoder::Step_WeightsU8() const -{ - u8 *wt = (u8 *)(decoded_ + decFmt.w0off); - const u8 *wdata = (const u8*)(ptr_); - int j; - for (j = 0; j < nweights; j++) - wt[j] = wdata[j]; - while (j & 3) // Zero additional weights rounding up to 4. - wt[j++] = 0; -} - -void VertexDecoder::Step_WeightsU16() const -{ - u16 *wt = (u16 *)(decoded_ + decFmt.w0off); - const u16 *wdata = (const u16*)(ptr_); - int j; - for (j = 0; j < nweights; j++) - wt[j] = wdata[j]; - while (j & 3) // Zero additional weights rounding up to 4. - wt[j++] = 0; -} - -void VertexDecoder::Step_WeightsU8ToFloat() const -{ - float *wt = (float *)(decoded_ + decFmt.w0off); - const u8 *wdata = (const u8*)(ptr_); - int j; - for (j = 0; j < nweights; j++) { - wt[j] = (float)wdata[j] * (1.0f / 128.0f); - } - while (j & 3) // Zero additional weights rounding up to 4. - wt[j++] = 0; -} - -void VertexDecoder::Step_WeightsU16ToFloat() const -{ - float *wt = (float *)(decoded_ + decFmt.w0off); - const u16 *wdata = (const u16*)(ptr_); - int j; - for (j = 0; j < nweights; j++) { - wt[j] = (float)wdata[j] * (1.0f / 32768.0f); - } - while (j & 3) // Zero additional weights rounding up to 4. - wt[j++] = 0; -} - -// Float weights should be uncommon, we can live with having to multiply these by 2.0 -// to avoid special checks in the vertex shader generator. -// (PSP uses 0.0-2.0 fixed point numbers for weights) -void VertexDecoder::Step_WeightsFloat() const -{ - float *wt = (float *)(decoded_ + decFmt.w0off); - const float *wdata = (const float*)(ptr_); - int j; - for (j = 0; j < nweights; j++) { - wt[j] = wdata[j]; - } - while (j & 3) // Zero additional weights rounding up to 4. - wt[j++] = 0.0f; -} - void VertexDecoder::ComputeSkinMatrix(const float weights[8]) const { memset(skinMatrix, 0, sizeof(skinMatrix)); for (int j = 0; j < nweights; j++) { @@ -851,20 +790,6 @@ void VertexDecoder::Step_PosFloatMorphSkin() const { Vec3ByMatrix43(v, pos, skinMatrix); } -static const StepFunction wtstep[4] = { - 0, - &VertexDecoder::Step_WeightsU8, - &VertexDecoder::Step_WeightsU16, - &VertexDecoder::Step_WeightsFloat, -}; - -static const StepFunction wtstepToFloat[4] = { - 0, - &VertexDecoder::Step_WeightsU8ToFloat, - &VertexDecoder::Step_WeightsU16ToFloat, - &VertexDecoder::Step_WeightsFloat, -}; - // TODO: Morph weights correctly! This is missing. Not sure if any game actually // use this functionality at all. diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index cabfc5138d..d5395704f1 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -460,12 +460,6 @@ public: std::string GetString(DebugShaderStringType stringType); - void Step_WeightsU8() const; - void Step_WeightsU16() const; - void Step_WeightsU8ToFloat() const; - void Step_WeightsU16ToFloat() const; - void Step_WeightsFloat() const; - void ComputeSkinMatrix(const float weights[8]) const; void Step_WeightsU8Skin() const; @@ -618,12 +612,6 @@ public: JittedVertexDecoder Compile(const VertexDecoder &dec, int32_t *jittedSize); void Clear(); - void Jit_WeightsU8(); - void Jit_WeightsU16(); - void Jit_WeightsU8ToFloat(); - void Jit_WeightsU16ToFloat(); - void Jit_WeightsFloat(); - void Jit_WeightsU8Skin(); void Jit_WeightsU16Skin(); void Jit_WeightsFloatSkin(); diff --git a/GPU/Common/VertexDecoderX86.cpp b/GPU/Common/VertexDecoderX86.cpp index 5098b2a7d4..70c5131e81 100644 --- a/GPU/Common/VertexDecoderX86.cpp +++ b/GPU/Common/VertexDecoderX86.cpp @@ -87,16 +87,10 @@ static const X64Reg fpScratchReg4 = XMM4; // on the interpreter if the compiler fails. static const JitLookup jitLookup[] = { - {&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8}, - {&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16}, - {&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat}, {&VertexDecoder::Step_WeightsU8Skin, &VertexDecoderJitCache::Jit_WeightsU8Skin}, {&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin}, {&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin}, - {&VertexDecoder::Step_WeightsU8ToFloat, &VertexDecoderJitCache::Jit_WeightsU8ToFloat}, - {&VertexDecoder::Step_WeightsU16ToFloat, &VertexDecoderJitCache::Jit_WeightsU16ToFloat}, - {&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat}, {&VertexDecoder::Step_TcU8ToFloat, &VertexDecoderJitCache::Jit_TcU8ToFloat}, {&VertexDecoder::Step_TcU16ToFloat, &VertexDecoderJitCache::Jit_TcU16ToFloat}, @@ -281,175 +275,6 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int return (JittedVertexDecoder)start; } -void VertexDecoderJitCache::Jit_WeightsU8() { - switch (dec_->nweights) { - case 1: - MOVZX(32, 8, tempReg1, MDisp(srcReg, dec_->weightoff)); - break; - case 2: - MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->weightoff)); - break; - case 3: - MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); - AND(32, R(tempReg1), Imm32(0x00FFFFFF)); - break; - case 4: - MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); - break; - case 5: - MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); - MOVZX(32, 8, tempReg2, MDisp(srcReg, dec_->weightoff + 4)); - break; - case 6: - MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); - MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->weightoff + 4)); - break; - case 7: - MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); - MOV(32, R(tempReg2), MDisp(srcReg, dec_->weightoff + 4)); - AND(32, R(tempReg2), Imm32(0x00FFFFFF)); - break; - case 8: - MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); - MOV(32, R(tempReg2), MDisp(srcReg, dec_->weightoff + 4)); - break; - } - - if (dec_->nweights <= 4) { - MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); - } else { - MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); - MOV(32, MDisp(dstReg, dec_->decFmt.w1off), R(tempReg2)); - } -} - -void VertexDecoderJitCache::Jit_WeightsU16() { - switch (dec_->nweights) { - case 1: - MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->weightoff)); - MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); - MOV(32, MDisp(dstReg, dec_->decFmt.w0off + 4), Imm32(0)); - return; - - case 2: - MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); - MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); - MOV(32, MDisp(dstReg, dec_->decFmt.w0off + 4), Imm32(0)); - return; - - case 3: - MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); - MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->weightoff + 4)); - MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); - MOV(32, MDisp(dstReg, dec_->decFmt.w0off + 4), R(tempReg2)); - return; - - case 4: - // Anything above 4 will do 4 here, and then the rest after. - case 5: - case 6: - case 7: - case 8: - MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); - MOV(32, R(tempReg2), MDisp(srcReg, dec_->weightoff + 4)); - MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); - MOV(32, MDisp(dstReg, dec_->decFmt.w0off + 4), R(tempReg2)); - break; - } - - // Basic implementation - a short at a time. TODO: Optimize - int j; - for (j = 4; j < dec_->nweights; j++) { - MOV(16, R(tempReg1), MDisp(srcReg, dec_->weightoff + j * 2)); - MOV(16, MDisp(dstReg, dec_->decFmt.w0off + j * 2), R(tempReg1)); - } - while (j & 3) { - MOV(16, MDisp(dstReg, dec_->decFmt.w0off + j * 2), Imm16(0)); - j++; - } -} - -void VertexDecoderJitCache::Jit_WeightsU8ToFloat() { - if (dec_->nweights >= 4) { - Jit_AnyU8ToFloat(dec_->weightoff, 32); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3); - if (dec_->nweights > 4) { - Jit_AnyU8ToFloat(dec_->weightoff + 4, (dec_->nweights - 4) * 8); - MOVUPS(MDisp(dstReg, dec_->decFmt.w1off), XMM3); - } - } else { - Jit_AnyU8ToFloat(dec_->weightoff, dec_->nweights * 8); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3); - } -} - -void VertexDecoderJitCache::Jit_WeightsU16ToFloat() { - if (dec_->nweights >= 4) { - Jit_AnyU16ToFloat(dec_->weightoff, 64); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3); - if (dec_->nweights > 4) { - Jit_AnyU16ToFloat(dec_->weightoff + 4 * 2, (dec_->nweights - 4) * 16); - MOVUPS(MDisp(dstReg, dec_->decFmt.w1off), XMM3); - } - } else { - Jit_AnyU16ToFloat(dec_->weightoff, dec_->nweights * 16); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3); - } -} - -void VertexDecoderJitCache::Jit_WeightsFloat() { - int j; - switch (dec_->nweights) { - case 1: - // MOVSS: When the source operand is a memory location and destination operand is an XMM register, the three high-order doublewords of the destination operand are cleared to all 0s. - MOVSS(XMM3, MDisp(srcReg, dec_->weightoff)); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3); - break; - - case 2: - MOVQ_xmm(XMM3, MDisp(srcReg, dec_->weightoff)); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3); - break; - - case 4: - MOVUPS(XMM3, MDisp(srcReg, dec_->weightoff)); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3); - break; - - case 5: - MOVUPS(XMM3, MDisp(srcReg, dec_->weightoff)); - MOVSS(XMM4, MDisp(srcReg, dec_->weightoff + 16)); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off + 16), XMM4); - break; - - case 6: - MOVUPS(XMM3, MDisp(srcReg, dec_->weightoff)); - MOVQ_xmm(XMM4, MDisp(srcReg, dec_->weightoff + 16)); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off + 16), XMM4); - break; - - case 8: - MOVUPS(XMM3, MDisp(srcReg, dec_->weightoff)); - MOVUPS(XMM4, MDisp(srcReg, dec_->weightoff + 16)); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3); - MOVUPS(MDisp(dstReg, dec_->decFmt.w0off + 16), XMM4); - break; - - default: - for (j = 0; j < dec_->nweights; j++) { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff + j * 4)); - MOV(32, MDisp(dstReg, dec_->decFmt.w0off + j * 4), R(tempReg1)); - } - while (j & 3) { // Zero additional weights rounding up to 4. - MOV(32, MDisp(dstReg, dec_->decFmt.w0off + j * 4), Imm32(0)); - j++; - } - break; - } -} - void VertexDecoderJitCache::Jit_WeightsU8Skin() { MOV(PTRBITS, R(tempReg2), ImmPtr(&bones)); From 40db61a6808cb7bab534d6de9010ccce7212c8ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 2 Mar 2018 14:19:38 +0100 Subject: [PATCH 226/291] Remove further remains of hardware skinning. Fixes #10661 --- Core/Config.cpp | 1 - Core/Config.h | 1 - GPU/Common/DrawEngineCommon.cpp | 59 +--------- GPU/Common/ShaderCommon.h | 12 +- GPU/Common/ShaderId.cpp | 11 -- GPU/Common/ShaderId.h | 6 +- GPU/Common/ShaderUniforms.cpp | 8 -- GPU/Common/ShaderUniforms.h | 17 --- GPU/Common/SoftwareTransformCommon.cpp | 50 ++------- GPU/Common/VertexDecoderArm.cpp | 2 +- GPU/Common/VertexDecoderArm64.cpp | 2 +- GPU/Common/VertexDecoderX86.cpp | 2 +- GPU/D3D11/DrawEngineD3D11.cpp | 2 +- GPU/D3D11/GPU_D3D11.cpp | 2 - GPU/D3D11/ShaderManagerD3D11.cpp | 15 +-- GPU/D3D11/ShaderManagerD3D11.h | 5 - GPU/Directx9/DrawEngineDX9.cpp | 2 +- GPU/Directx9/GPU_DX9.cpp | 4 - GPU/Directx9/ShaderManagerDX9.cpp | 34 +----- GPU/Directx9/VertexShaderGeneratorDX9.cpp | 101 +---------------- GPU/Directx9/VertexShaderGeneratorDX9.h | 53 ++++----- GPU/GLES/DrawEngineGLES.cpp | 4 +- GPU/GLES/GPU_GLES.cpp | 4 - GPU/GLES/ShaderManagerGLES.cpp | 22 +--- GPU/GLES/ShaderManagerGLES.h | 7 -- GPU/GLES/VertexShaderGeneratorGLES.cpp | 125 +-------------------- GPU/GLES/VertexShaderGeneratorGLES.h | 2 - GPU/GPUCommon.cpp | 86 ++------------ GPU/GPUCommon.h | 3 - GPU/GPUState.cpp | 7 -- GPU/GPUState.h | 2 - GPU/Software/SoftGpu.cpp | 8 -- GPU/Software/TransformUnit.cpp | 21 ---- GPU/Vulkan/DrawEngineVulkan.cpp | 55 ++++----- GPU/Vulkan/DrawEngineVulkan.h | 9 +- GPU/Vulkan/GPU_Vulkan.cpp | 2 - GPU/Vulkan/PipelineManagerVulkan.cpp | 3 - GPU/Vulkan/PipelineManagerVulkan.h | 3 +- GPU/Vulkan/ShaderManagerVulkan.cpp | 4 - GPU/Vulkan/ShaderManagerVulkan.h | 9 -- GPU/Vulkan/VertexShaderGeneratorVulkan.cpp | 52 +-------- UI/GameSettingsScreen.cpp | 7 -- ext/native/thin3d/VulkanQueueRunner.h | 2 +- headless/Headless.cpp | 1 - unittest/TestVertexJit.cpp | 3 - 45 files changed, 83 insertions(+), 747 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 8fae1b0f60..f89d75f738 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -501,7 +501,6 @@ static ConfigSetting graphicsSettings[] = { ReportedConfigSetting("RenderingMode", &g_Config.iRenderingMode, &DefaultRenderingMode, true, true), ConfigSetting("SoftwareRenderer", &g_Config.bSoftwareRendering, false, true, true), ReportedConfigSetting("HardwareTransform", &g_Config.bHardwareTransform, true, true, true), - ReportedConfigSetting("SoftwareSkinning", &g_Config.bSoftwareSkinning, true, true, true), ReportedConfigSetting("TextureFiltering", &g_Config.iTexFiltering, 1, true, true), ReportedConfigSetting("BufferFiltering", &g_Config.iBufFilter, 1, true, true), ReportedConfigSetting("InternalResolution", &g_Config.iInternalResolution, &DefaultInternalResolution, true, true), diff --git a/Core/Config.h b/Core/Config.h index 78af006d04..43751c9a79 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -154,7 +154,6 @@ public: int iGPUBackend; bool bSoftwareRendering; bool bHardwareTransform; // only used in the GLES backend - bool bSoftwareSkinning; // may speed up some games int iRenderingMode; // 0 = non-buffered rendering 1 = buffered rendering int iTexFiltering; // 1 = off , 2 = nearest , 3 = linear , 4 = linear(CG) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index a3746d0874..472056893d 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -379,13 +379,9 @@ bool DrawEngineCommon::GetCurrentSimpleVertices(int count, std::vectorDecodeVerts(bufPtr, inPtr, lowerBound, upperBound); - // OK, morphing eliminated but bones still remain to be taken care of. - // Let's do a partial software transform where we only do skinning. - VertexReader reader(bufPtr, dec->GetDecVtxFmt(), vertType); SimpleVertex *sverts = (SimpleVertex *)outPtr; @@ -397,56 +393,7 @@ u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, (u8)gstate.getMaterialAmbientA(), }; - // Let's have two separate loops, one for non skinning and one for skinning. - if (!g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { - int numBoneWeights = vertTypeGetNumBoneWeights(vertType); - for (int i = lowerBound; i <= upperBound; i++) { - reader.Goto(i - lowerBound); - SimpleVertex &sv = sverts[i]; - if (vertType & GE_VTYPE_TC_MASK) { - reader.ReadUV(sv.uv); - } - - if (vertType & GE_VTYPE_COL_MASK) { - reader.ReadColor0_8888(sv.color); - } else { - memcpy(sv.color, defaultColor, 4); - } - - float nrm[3], pos[3]; - float bnrm[3], bpos[3]; - - if (vertType & GE_VTYPE_NRM_MASK) { - // Normals are generated during tessellation anyway, not sure if any need to supply - reader.ReadNrm(nrm); - } else { - nrm[0] = 0; - nrm[1] = 0; - nrm[2] = 1.0f; - } - reader.ReadPos(pos); - - // Apply skinning transform directly - float weights[8]; - reader.ReadWeights(weights); - // Skinning - Vec3Packedf psum(0, 0, 0); - Vec3Packedf nsum(0, 0, 0); - for (int w = 0; w < numBoneWeights; w++) { - if (weights[w] != 0.0f) { - Vec3ByMatrix43(bpos, pos, gstate.boneMatrix + w * 12); - Vec3Packedf tpos(bpos); - psum += tpos * weights[w]; - - Norm3ByMatrix43(bnrm, nrm, gstate.boneMatrix + w * 12); - Vec3Packedf tnorm(bnrm); - nsum += tnorm * weights[w]; - } - } - sv.pos = psum; - sv.nrm = nsum; - } - } else { + { for (int i = lowerBound; i <= upperBound; i++) { reader.Goto(i - lowerBound); SimpleVertex &sv = sverts[i]; @@ -711,7 +658,7 @@ void DrawEngineCommon::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, numDrawCalls++; vertexCountInDrawCalls_ += vertexCount; - if (g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK)) { + if (vertType & GE_VTYPE_WEIGHT_MASK) { DecodeVertsStep(decoded, decodeCounter_, decodedVerts_); decodeCounter_++; } diff --git a/GPU/Common/ShaderCommon.h b/GPU/Common/ShaderCommon.h index 6e4bfa8c81..8de756237c 100644 --- a/GPU/Common/ShaderCommon.h +++ b/GPU/Common/ShaderCommon.h @@ -76,14 +76,8 @@ enum : uint64_t { DIRTY_WORLDMATRIX = 1ULL << 21, DIRTY_VIEWMATRIX = 1ULL << 22, DIRTY_TEXMATRIX = 1ULL << 23, - DIRTY_BONEMATRIX0 = 1ULL << 24, // NOTE: These must be under 32 - DIRTY_BONEMATRIX1 = 1ULL << 25, - DIRTY_BONEMATRIX2 = 1ULL << 26, - DIRTY_BONEMATRIX3 = 1ULL << 27, - DIRTY_BONEMATRIX4 = 1ULL << 28, - DIRTY_BONEMATRIX5 = 1ULL << 29, - DIRTY_BONEMATRIX6 = 1ULL << 30, - DIRTY_BONEMATRIX7 = 1ULL << 31, + + // 8 free bits here where bones used to be! // These are for hardware tessellation DIRTY_BEZIERSPLINE = 1ULL << 32, @@ -91,8 +85,6 @@ enum : uint64_t { // space for 7 more uniforms. - DIRTY_BONE_UNIFORMS = 0xFF000000ULL, - DIRTY_ALL_UNIFORMS = 0x3FFFFFFFFULL, DIRTY_ALL_LIGHTS = DIRTY_LIGHT0 | DIRTY_LIGHT1 | DIRTY_LIGHT2 | DIRTY_LIGHT3, diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index 3a8f0de37e..8a1667f181 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -33,7 +33,6 @@ std::string VertexShaderDesc(const ShaderID &id) { int ls1 = id.Bits(VS_BIT_LS1, 2); if (uvgMode) desc << uvgModes[uvgMode]; - if (id.Bit(VS_BIT_ENABLE_BONES)) desc << "Bones:" << (id.Bits(VS_BIT_BONES, 3) + 1) << " "; // Lights if (id.Bit(VS_BIT_LIGHTING_ENABLE)) { desc << "Light: "; @@ -103,16 +102,6 @@ void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform) id.SetBits(VS_BIT_LS1, 2, gstate.getUVLS1()); } - // Bones. - bool enableBones = vertTypeIsSkinningEnabled(vertType); - id.SetBit(VS_BIT_ENABLE_BONES, enableBones); - if (enableBones) { - id.SetBits(VS_BIT_BONES, 3, TranslateNumBones(vertTypeGetNumBoneWeights(vertType)) - 1); - // 2 bits. We should probably send in the weight scalefactor as a uniform instead, - // or simply preconvert all weights to floats. - id.SetBits(VS_BIT_WEIGHT_FMTSCALE, 2, (vertType & GE_VTYPE_WEIGHT_MASK) >> GE_VTYPE_WEIGHT_SHIFT); - } - // Okay, d[1] coming up. ============== if (gstate.isLightingEnabled() || doShadeMapping) { // doShadeMapping is stored as UVGenMode, so this is enough for isLightingEnabled. diff --git a/GPU/Common/ShaderId.h b/GPU/Common/ShaderId.h index afc7c51313..8ef501a571 100644 --- a/GPU/Common/ShaderId.h +++ b/GPU/Common/ShaderId.h @@ -7,7 +7,6 @@ // TODO: There will be additional bits, indicating that groups of these will be // sent to the shader and processed there. This will cut down the number of shaders ("ubershader approach") -// This is probably only really worth doing for lighting and bones. enum { VS_BIT_LMODE = 0, VS_BIT_IS_THROUGH = 1, @@ -29,10 +28,7 @@ enum { VS_BIT_UVPROJ_MODE = 18, // 2, can overlap with LS0 VS_BIT_LS0 = 18, // 2 VS_BIT_LS1 = 20, // 2 - VS_BIT_BONES = 22, // 3 should be enough, not 8 - // 25 - 29 are free. - VS_BIT_ENABLE_BONES = 30, - // 31 is free. + // 22 - 31 are free. VS_BIT_LIGHT0_COMP = 32, // 2 bits VS_BIT_LIGHT0_TYPE = 34, // 2 bits VS_BIT_LIGHT1_COMP = 36, // 2 bits diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index a057574961..302c930673 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -246,11 +246,3 @@ void LightUpdateUniforms(UB_VS_Lights *ub, uint64_t dirtyUniforms) { } } } - -void BoneUpdateUniforms(UB_VS_Bones *ub, uint64_t dirtyUniforms) { - for (int i = 0; i < 8; i++) { - if (dirtyUniforms & (DIRTY_BONEMATRIX0 << i)) { - ConvertMatrix4x3To3x4Transposed(ub->bones[i], gstate.boneMatrix + 12 * i); - } - } -} diff --git a/GPU/Common/ShaderUniforms.h b/GPU/Common/ShaderUniforms.h index 1dc5065185..82bc27a33b 100644 --- a/GPU/Common/ShaderUniforms.h +++ b/GPU/Common/ShaderUniforms.h @@ -164,22 +164,5 @@ R"( float4 u_ambient; float3 u_lightspecular3; )"; -// With some cleverness, we could get away with uploading just half this when only the four or five first -// bones are being used. This is 512b, 256b would be great. -struct UB_VS_Bones { - float bones[8][12]; -}; - -static const char *ub_vs_bonesStr = -R"( mat3x4 m[8]; -)"; - -// HLSL code is shared so these names are changed to match those in DX9. -static const char *cb_vs_bonesStr = -R"( float4x3 u_bone[8]; -)"; - void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipViewport); void LightUpdateUniforms(UB_VS_Lights *ub, uint64_t dirtyUniforms); -void BoneUpdateUniforms(UB_VS_Bones *ub, uint64_t dirtyUniforms); - diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index a29c987c11..5ebf13570c 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -144,8 +144,6 @@ void SoftwareTransform( vscale /= gstate_c.curTextureHeight; } - bool skinningEnabled = vertTypeIsSkinningEnabled(vertType); - const int w = gstate.getTextureWidth(0); const int h = gstate.getTextureHeight(0); float widthFactor = (float) w / (float) gstate_c.curTextureWidth; @@ -213,48 +211,14 @@ void SoftwareTransform( Vec3f worldnormal(0, 0, 1); reader.ReadPos(pos); - if (!skinningEnabled) { - Vec3ByMatrix43(out, pos, gstate.worldMatrix); - if (reader.hasNormal()) { - reader.ReadNrm(normal.AsArray()); - if (gstate.areNormalsReversed()) { - normal = -normal; - } - Norm3ByMatrix43(worldnormal.AsArray(), normal.AsArray(), gstate.worldMatrix); - worldnormal = worldnormal.Normalized(); - } - } else { - float weights[8]; - reader.ReadWeights(weights); - if (reader.hasNormal()) - reader.ReadNrm(normal.AsArray()); - - // Skinning - Vec3f psum(0, 0, 0); - Vec3f nsum(0, 0, 0); - for (int i = 0; i < vertTypeGetNumBoneWeights(vertType); i++) { - if (weights[i] != 0.0f) { - Vec3ByMatrix43(out, pos, gstate.boneMatrix+i*12); - Vec3f tpos(out); - psum += tpos * weights[i]; - if (reader.hasNormal()) { - Vec3f norm; - Norm3ByMatrix43(norm.AsArray(), normal.AsArray(), gstate.boneMatrix+i*12); - nsum += norm * weights[i]; - } - } - } - - // Yes, we really must multiply by the world matrix too. - Vec3ByMatrix43(out, psum.AsArray(), gstate.worldMatrix); - if (reader.hasNormal()) { - normal = nsum; - if (gstate.areNormalsReversed()) { - normal = -normal; - } - Norm3ByMatrix43(worldnormal.AsArray(), normal.AsArray(), gstate.worldMatrix); - worldnormal = worldnormal.Normalized(); + Vec3ByMatrix43(out, pos, gstate.worldMatrix); + if (reader.hasNormal()) { + reader.ReadNrm(normal.AsArray()); + if (gstate.areNormalsReversed()) { + normal = -normal; } + Norm3ByMatrix43(worldnormal.AsArray(), normal.AsArray(), gstate.worldMatrix); + worldnormal = worldnormal.Normalized(); } // Perform lighting here if enabled. don't need to check through, it's checked above. diff --git a/GPU/Common/VertexDecoderArm.cpp b/GPU/Common/VertexDecoderArm.cpp index 79e6584ae2..c7cddcb4de 100644 --- a/GPU/Common/VertexDecoderArm.cpp +++ b/GPU/Common/VertexDecoderArm.cpp @@ -229,7 +229,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int // Add code to convert matrices to 4x4. // Later we might want to do this when the matrices are loaded instead. int boneCount = 0; - if (NEONSkinning && dec.weighttype && g_Config.bSoftwareSkinning && dec.morphcount == 1) { + if (NEONSkinning && dec.weighttype) { // Copying from R3 to R4 MOVP2R(R3, gstate.boneMatrix); MOVP2R(R4, bones); diff --git a/GPU/Common/VertexDecoderArm64.cpp b/GPU/Common/VertexDecoderArm64.cpp index acfa230ea9..3c87a6b677 100644 --- a/GPU/Common/VertexDecoderArm64.cpp +++ b/GPU/Common/VertexDecoderArm64.cpp @@ -193,7 +193,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int // Add code to convert matrices to 4x4. // Later we might want to do this when the matrices are loaded instead. int boneCount = 0; - if (dec.weighttype && g_Config.bSoftwareSkinning && dec.morphcount == 1) { + if (dec.weighttype) { // Copying from R3 to R4 MOVP2R(X3, gstate.boneMatrix); MOVP2R(X4, bones); diff --git a/GPU/Common/VertexDecoderX86.cpp b/GPU/Common/VertexDecoderX86.cpp index 70c5131e81..388be1e2d7 100644 --- a/GPU/Common/VertexDecoderX86.cpp +++ b/GPU/Common/VertexDecoderX86.cpp @@ -195,7 +195,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int // Add code to convert matrices to 4x4. // Later we might want to do this when the matrices are loaded instead. int boneCount = 0; - if (dec.weighttype && g_Config.bSoftwareSkinning && dec.morphcount == 1) { + if (dec.weighttype) { MOV(PTRBITS, R(tempReg1), ImmPtr(&threeMasks)); MOVAPS(XMM4, MatR(tempReg1)); MOV(PTRBITS, R(tempReg1), ImmPtr(&aOne)); diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 2b49ae2d6e..55006baca7 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -344,7 +344,7 @@ void DrawEngineD3D11::DoFlush() { // Cannot cache vertex data with morph enabled. bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); // Also avoid caching when software skinning. - if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) + if (lastVType_ & GE_VTYPE_WEIGHT_MASK) useCache = false; if (useCache) { diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 8ad9ebd11a..2b5d760302 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -103,7 +103,6 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) // No need to flush before the tex scale/offset commands if we are baking // the tex scale/offset into the vertices anyway. - UpdateCmdInfo(); CheckGPUFeatures(); BuildReportingInfo(); @@ -215,7 +214,6 @@ void GPU_D3D11::InitClear() { void GPU_D3D11::BeginHostFrame() { GPUCommon::BeginHostFrame(); - UpdateCmdInfo(); if (resized_) { CheckGPUFeatures(); framebufferManager_->Resized(); diff --git a/GPU/D3D11/ShaderManagerD3D11.cpp b/GPU/D3D11/ShaderManagerD3D11.cpp index 75f8d9535e..3efb79ace3 100644 --- a/GPU/D3D11/ShaderManagerD3D11.cpp +++ b/GPU/D3D11/ShaderManagerD3D11.cpp @@ -93,24 +93,19 @@ ShaderManagerD3D11::ShaderManagerD3D11(ID3D11Device *device, ID3D11DeviceContext codeBuffer_ = new char[16384]; memset(&ub_base, 0, sizeof(ub_base)); memset(&ub_lights, 0, sizeof(ub_lights)); - memset(&ub_bones, 0, sizeof(ub_bones)); INFO_LOG(G3D, "sizeof(ub_base): %d", (int)sizeof(ub_base)); INFO_LOG(G3D, "sizeof(ub_lights): %d", (int)sizeof(ub_lights)); - INFO_LOG(G3D, "sizeof(ub_bones): %d", (int)sizeof(ub_bones)); D3D11_BUFFER_DESC desc{sizeof(ub_base), D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE }; ASSERT_SUCCESS(device_->CreateBuffer(&desc, nullptr, &push_base)); desc.ByteWidth = sizeof(ub_lights); ASSERT_SUCCESS(device_->CreateBuffer(&desc, nullptr, &push_lights)); - desc.ByteWidth = sizeof(ub_bones); - ASSERT_SUCCESS(device_->CreateBuffer(&desc, nullptr, &push_bones)); } ShaderManagerD3D11::~ShaderManagerD3D11() { push_base->Release(); push_lights->Release(); - push_bones->Release(); ClearShaders(); delete[] codeBuffer_; } @@ -159,21 +154,15 @@ uint64_t ShaderManagerD3D11::UpdateUniforms() { memcpy(map.pData, &ub_lights, sizeof(ub_lights)); context_->Unmap(push_lights, 0); } - if (dirty & DIRTY_BONE_UNIFORMS) { - BoneUpdateUniforms(&ub_bones, dirty); - context_->Map(push_bones, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - memcpy(map.pData, &ub_bones, sizeof(ub_bones)); - context_->Unmap(push_bones, 0); - } } gstate_c.CleanUniforms(); return dirty; } void ShaderManagerD3D11::BindUniforms() { - ID3D11Buffer *vs_cbs[3] = { push_base, push_lights, push_bones }; + ID3D11Buffer *vs_cbs[2] = { push_base, push_lights }; ID3D11Buffer *ps_cbs[1] = { push_base }; - context_->VSSetConstantBuffers(0, 3, vs_cbs); + context_->VSSetConstantBuffers(0, 2, vs_cbs); context_->PSSetConstantBuffers(0, 1, ps_cbs); } diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index 3d66c9dfb5..1ca3db44bb 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -61,9 +61,6 @@ public: const std::vector &bytecode() const { return bytecode_; } bool Failed() const { return failed_; } bool UseHWTransform() const { return useHWTransform_; } - bool HasBones() const { - return id_.Bit(VS_BIT_ENABLE_BONES); - } bool HasLights() const { return usesLighting_; } @@ -134,12 +131,10 @@ private: // Uniform block scratchpad. These (the relevant ones) are copied to the current pushbuffer at draw time. UB_VS_FS_Base ub_base; UB_VS_Lights ub_lights; - UB_VS_Bones ub_bones; // Not actual pushbuffers, requires D3D11.1, let's try to live without that first. ID3D11Buffer *push_base; ID3D11Buffer *push_lights; - ID3D11Buffer *push_bones; D3D11FragmentShader *lastFShader_; D3D11VertexShader *lastVShader_; diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index c72d256727..9330893a97 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -325,7 +325,7 @@ void DrawEngineDX9::DoFlush() { // Cannot cache vertex data with morph enabled. bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); // Also avoid caching when software skinning. - if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) + if (lastVType_ & GE_VTYPE_WEIGHT_MASK) useCache = false; if (useCache) { diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index adb50ecbf0..52f1a6e2d6 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -83,9 +83,6 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) ERROR_LOG(G3D, "gstate has drifted out of sync!"); } - // No need to flush before the tex scale/offset commands if we are baking - // the tex scale/offset into the vertices anyway. - UpdateCmdInfo(); CheckGPUFeatures(); BuildReportingInfo(); @@ -191,7 +188,6 @@ void GPU_DX9::InitClear() { void GPU_DX9::BeginHostFrame() { GPUCommon::BeginHostFrame(); - UpdateCmdInfo(); if (resized_) { CheckGPUFeatures(); framebufferManager_->Resized(); diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 2f5fdad0ce..291446017f 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -313,7 +313,7 @@ void ShaderManagerDX9::PSUpdateUniforms(u64 dirtyUniforms) { } const uint64_t vsUniforms = DIRTY_PROJMATRIX | DIRTY_PROJTHROUGHMATRIX | DIRTY_WORLDMATRIX | DIRTY_VIEWMATRIX | DIRTY_TEXMATRIX | -DIRTY_FOGCOEF | DIRTY_BONE_UNIFORMS | DIRTY_UVSCALEOFFSET | DIRTY_DEPTHRANGE | +DIRTY_FOGCOEF | DIRTY_UVSCALEOFFSET | DIRTY_DEPTHRANGE | DIRTY_AMBIENT | DIRTY_MATAMBIENTALPHA | DIRTY_MATSPECULAR | DIRTY_MATDIFFUSE | DIRTY_MATEMISSIVE | DIRTY_LIGHT0 | DIRTY_LIGHT1 | DIRTY_LIGHT2 | DIRTY_LIGHT3; void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { @@ -382,38 +382,6 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { #endif VSSetFloatArray(CONST_VS_FOGCOEF, fogcoef, 2); } - // TODO: Could even set all bones in one go if they're all dirty. -#ifdef USE_BONE_ARRAY - if (u_bone != 0) { - float allBones[8 * 16]; - - bool allDirty = true; - for (int i = 0; i < numBones; i++) { - if (dirtyUniforms & (DIRTY_BONEMATRIX0 << i)) { - ConvertMatrix4x3To4x4(allBones + 16 * i, gstate.boneMatrix + 12 * i); - } else { - allDirty = false; - } - } - if (allDirty) { - // Set them all with one call - //glUniformMatrix4fv(u_bone, numBones, GL_FALSE, allBones); - } else { - // Set them one by one. Could try to coalesce two in a row etc but too lazy. - for (int i = 0; i < numBones; i++) { - if (dirtyUniforms & (DIRTY_BONEMATRIX0 << i)) { - //glUniformMatrix4fv(u_bone + i, 1, GL_FALSE, allBones + 16 * i); - } - } - } - } -#else - for (int i = 0; i < 8; i++) { - if (dirtyUniforms & (DIRTY_BONEMATRIX0 << i)) { - VSSetMatrix4x3_3(CONST_VS_BONE0 + 3 * i, gstate.boneMatrix + 12 * i); - } - } -#endif // Texturing if (dirtyUniforms & DIRTY_UVSCALEOFFSET) { diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.cpp b/GPU/Directx9/VertexShaderGeneratorDX9.cpp index 5158fb423d..8c37144401 100644 --- a/GPU/Directx9/VertexShaderGeneratorDX9.cpp +++ b/GPU/Directx9/VertexShaderGeneratorDX9.cpp @@ -37,19 +37,7 @@ namespace DX9 { -static const char * const boneWeightAttrDecl[9] = { - "#ERROR#", - "float a_w1:TEXCOORD1;\n", - "float2 a_w1:TEXCOORD1;\n", - "float3 a_w1:TEXCOORD1;\n", - "float4 a_w1:TEXCOORD1;\n", - "float4 a_w1:TEXCOORD1;\n float a_w2:TEXCOORD2;\n", - "float4 a_w1:TEXCOORD1;\n float2 a_w2:TEXCOORD2;\n", - "float4 a_w1:TEXCOORD1;\n float3 a_w2:TEXCOORD2;\n", - "float4 a_w1:TEXCOORD1;\n float4 a_w2:TEXCOORD2;\n", -}; - -enum DoLightComputation { + enum DoLightComputation { LIGHT_OFF, LIGHT_SHADE, LIGHT_FULL, @@ -80,7 +68,6 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage bool flipNormal = id.Bit(VS_BIT_NORM_REVERSE); int ls0 = id.Bits(VS_BIT_LS0, 2); int ls1 = id.Bits(VS_BIT_LS1, 2); - bool enableBones = id.Bit(VS_BIT_ENABLE_BONES); bool enableLighting = id.Bit(VS_BIT_LIGHTING_ENABLE); int matUpdate = id.Bits(VS_BIT_MATERIAL_UPDATE, 3); @@ -104,9 +91,6 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage int numBoneWeights = 0; int boneWeightScale = id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2); - if (enableBones) { - numBoneWeights = 1 + id.Bits(VS_BIT_BONES, 3); - } if (lang == HLSL_DX9) { WRITE(p, "#pragma warning( disable : 3571 )\n"); @@ -129,15 +113,6 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage WRITE(p, "float4x3 u_view : register(c%i);\n", CONST_VS_VIEW); if (doTextureTransform) WRITE(p, "float4x3 u_tex : register(c%i);\n", CONST_VS_TEXMTX); - if (enableBones) { -#ifdef USE_BONE_ARRAY - WRITE(p, "float4x3 u_bone[%i] : register(c%i);\n", numBones, CONST_VS_BONE0); -#else - for (int i = 0; i < numBoneWeights; i++) { - WRITE(p, "float4x3 u_bone%i : register(c%i);\n", i, CONST_VS_BONE0 + i * 3); - } -#endif - } if (doTexture) { WRITE(p, "float4 u_uvscaleoffset : register(c%i);\n", CONST_VS_UVSCALEOFFSET); } @@ -182,7 +157,6 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage } else { WRITE(p, "cbuffer base : register(b0) {\n%s};\n", cb_baseStr); WRITE(p, "cbuffer lights: register(b1) {\n%s};\n", cb_vs_lightsStr); - WRITE(p, "cbuffer bones : register(b2) {\n%s};\n", cb_vs_bonesStr); } // And the "varyings". @@ -192,9 +166,6 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage if ((doSpline || doBezier) && lang == HLSL_D3D11) { WRITE(p, " uint instanceId : SV_InstanceID;\n"); } - if (enableBones) { - WRITE(p, " %s", boneWeightAttrDecl[numBoneWeights]); - } if (doTexture && hasTexcoord) { WRITE(p, " float2 texcoord : TEXCOORD0;\n"); } @@ -388,7 +359,7 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage } } else { // Step 1: World Transform / Skinning - if (!enableBones) { + if (true) { // Hardware tessellation if (doSpline || doBezier) { WRITE(p, " uint num_patches_u = %s;\n", doBezier ? "(u_spline_count_u - 1) / 3u" : "u_spline_count_u - 3"); @@ -497,74 +468,6 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage else WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n"); } - } else { - static const char * const boneWeightAttr[8] = { - "a_w1.x", "a_w1.y", "a_w1.z", "a_w1.w", - "a_w2.x", "a_w2.y", "a_w2.z", "a_w2.w", - }; - -#if defined(USE_FOR_LOOP) && defined(USE_BONE_ARRAY) - - // To loop through the weights, we unfortunately need to put them in a float array. - // GLSL ES sucks - no way to directly initialize an array! - switch (numBoneWeights) { - case 1: WRITE(p, " float w[1]; w[0] = a_w1;\n"); break; - case 2: WRITE(p, " float w[2]; w[0] = a_w1.x; w[1] = a_w1.y;\n"); break; - case 3: WRITE(p, " float w[3]; w[0] = a_w1.x; w[1] = a_w1.y; w[2] = a_w1.z;\n"); break; - case 4: WRITE(p, " float w[4]; w[0] = a_w1.x; w[1] = a_w1.y; w[2] = a_w1.z; w[3] = a_w1.w;\n"); break; - case 5: WRITE(p, " float w[5]; w[0] = a_w1.x; w[1] = a_w1.y; w[2] = a_w1.z; w[3] = a_w1.w; w[4] = a_w2;\n"); break; - case 6: WRITE(p, " float w[6]; w[0] = a_w1.x; w[1] = a_w1.y; w[2] = a_w1.z; w[3] = a_w1.w; w[4] = a_w2.x; w[5] = a_w2.y;\n"); break; - case 7: WRITE(p, " float w[7]; w[0] = a_w1.x; w[1] = a_w1.y; w[2] = a_w1.z; w[3] = a_w1.w; w[4] = a_w2.x; w[5] = a_w2.y; w[6] = a_w2.z;\n"); break; - case 8: WRITE(p, " float w[8]; w[0] = a_w1.x; w[1] = a_w1.y; w[2] = a_w1.z; w[3] = a_w1.w; w[4] = a_w2.x; w[5] = a_w2.y; w[6] = a_w2.z; w[7] = a_w2.w;\n"); break; - } - - WRITE(p, " mat4 skinMatrix = w[0] * u_bone[0];\n"); - if (numBoneWeights > 1) { - WRITE(p, " for (int i = 1; i < %i; i++) {\n", numBoneWeights); - WRITE(p, " skinMatrix += w[i] * u_bone[i];\n"); - WRITE(p, " }\n"); - } - -#else - if (lang == HLSL_D3D11 || lang == HLSL_D3D11_LEVEL9) { - if (numBoneWeights == 1) - WRITE(p, " float4x3 skinMatrix = mul(In.a_w1, u_bone[0])"); - else - WRITE(p, " float4x3 skinMatrix = mul(In.a_w1.x, u_bone[0])"); - for (int i = 1; i < numBoneWeights; i++) { - const char *weightAttr = boneWeightAttr[i]; - // workaround for "cant do .x of scalar" issue - if (numBoneWeights == 1 && i == 0) weightAttr = "a_w1"; - if (numBoneWeights == 5 && i == 4) weightAttr = "a_w2"; - WRITE(p, " + mul(In.%s, u_bone[%i])", weightAttr, i); - } - } else { - if (numBoneWeights == 1) - WRITE(p, " float4x3 skinMatrix = mul(In.a_w1, u_bone0)"); - else - WRITE(p, " float4x3 skinMatrix = mul(In.a_w1.x, u_bone0)"); - for (int i = 1; i < numBoneWeights; i++) { - const char *weightAttr = boneWeightAttr[i]; - // workaround for "cant do .x of scalar" issue - if (numBoneWeights == 1 && i == 0) weightAttr = "a_w1"; - if (numBoneWeights == 5 && i == 4) weightAttr = "a_w2"; - WRITE(p, " + mul(In.%s, u_bone%i)", weightAttr, i); - } - } -#endif - - WRITE(p, ";\n"); - - // Trying to simplify this results in bugs in LBP... - WRITE(p, " float3 skinnedpos = mul(float4(In.position.xyz, 1.0), skinMatrix);\n"); - WRITE(p, " float3 worldpos = mul(float4(skinnedpos, 1.0), u_world);\n"); - - if (hasNormal) { - WRITE(p, " float3 skinnednormal = mul(float4(%sIn.normal, 0.0), skinMatrix);\n", flipNormal ? "-" : ""); - } else { - WRITE(p, " float3 skinnednormal = mul(float4(0.0, 0.0, %s1.0, 0.0), skinMatrix);\n", flipNormal ? "-" : ""); - } - WRITE(p, " float3 worldnormal = normalize(mul(float4(skinnednormal, 0.0), u_world));\n"); } WRITE(p, " float4 viewPos = float4(mul(float4(worldpos, 1.0), u_view), 1.0);\n"); diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.h b/GPU/Directx9/VertexShaderGeneratorDX9.h index a48c110d39..585fec012a 100644 --- a/GPU/Directx9/VertexShaderGeneratorDX9.h +++ b/GPU/Directx9/VertexShaderGeneratorDX9.h @@ -25,35 +25,28 @@ namespace DX9 { void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage lang = HLSL_DX9); -#define CONST_VS_PROJ 0 -#define CONST_VS_PROJ_THROUGH 4 -#define CONST_VS_VIEW 8 -#define CONST_VS_WORLD 11 -#define CONST_VS_TEXMTX 14 -#define CONST_VS_UVSCALEOFFSET 17 -#define CONST_VS_FOGCOEF 18 -#define CONST_VS_AMBIENT 19 -#define CONST_VS_BONE0 20 -#define CONST_VS_BONE1 23 -#define CONST_VS_BONE2 26 -#define CONST_VS_BONE3 29 -#define CONST_VS_BONE4 32 -#define CONST_VS_BONE5 35 -#define CONST_VS_BONE6 38 -#define CONST_VS_BONE7 41 -#define CONST_VS_BONE8 44 -#define CONST_VS_MATAMBIENTALPHA 47 -#define CONST_VS_MATDIFFUSE 48 -#define CONST_VS_MATSPECULAR 49 -#define CONST_VS_MATEMISSIVE 50 -#define CONST_VS_LIGHTPOS 51 -#define CONST_VS_LIGHTDIR 55 -#define CONST_VS_LIGHTATT 59 -#define CONST_VS_LIGHTANGLE 63 -#define CONST_VS_LIGHTSPOTCOEF 67 -#define CONST_VS_LIGHTDIFFUSE 71 -#define CONST_VS_LIGHTSPECULAR 75 -#define CONST_VS_LIGHTAMBIENT 79 -#define CONST_VS_DEPTHRANGE 83 + enum { + CONST_VS_PROJ = 0, + CONST_VS_PROJ_THROUGH = 4, + CONST_VS_VIEW = 8, + CONST_VS_WORLD = 11, + CONST_VS_TEXMTX = 14, + CONST_VS_UVSCALEOFFSET = 17, + CONST_VS_FOGCOEF = 18, + CONST_VS_AMBIENT = 19, + CONST_VS_MATAMBIENTALPHA = 20, + CONST_VS_MATDIFFUSE = 21, + CONST_VS_MATSPECULAR = 22, + CONST_VS_MATEMISSIVE = 23, + CONST_VS_LIGHTPOS = 24, + CONST_VS_LIGHTDIR = 28, + CONST_VS_LIGHTATT = 32, + CONST_VS_LIGHTANGLE = 36, + CONST_VS_LIGHTSPOTCOEF = 40, + CONST_VS_LIGHTDIFFUSE = 44, + CONST_VS_LIGHTSPECULAR = 48, + CONST_VS_LIGHTAMBIENT = 52, + CONST_VS_DEPTHRANGE = 56, + }; }; diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 83b56e5cab..a02fe9f3c4 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -377,7 +377,7 @@ void DrawEngineGLES::DoFlush() { // Cannot cache vertex data with morph enabled. bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); // Also avoid caching when software skinning. - if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) + if (lastVType_ & GE_VTYPE_WEIGHT_MASK) useCache = false; // TEMPORARY @@ -521,7 +521,7 @@ void DrawEngineGLES::DoFlush() { vai->lastFrame = gpuStats.numFlips; } else { - if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { + if (lastVType_ & GE_VTYPE_WEIGHT_MASK) { // If software skinning, we've already predecoded into "decoded". So push that content. size_t size = decodedVerts_ * dec_->GetDecVtxFmt().stride; u8 *dest = (u8 *)frameData.pushVertex->Push(size, &vertexBufferOffset, &vertexBuffer); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index ea65a9faec..5b2e6445ac 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -89,8 +89,6 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) // No need to flush before the tex scale/offset commands if we are baking // the tex scale/offset into the vertices anyway. - UpdateCmdInfo(); - BuildReportingInfo(); // Update again after init to be sure of any silly driver problems. UpdateVsyncInterval(true); @@ -346,7 +344,6 @@ void GPU_GLES::DeviceRestore() { draw_ = (Draw::DrawContext *)PSP_CoreParameter().graphicsContext->GetDrawContext(); ILOG("GPU_GLES: DeviceRestore"); - UpdateCmdInfo(); UpdateVsyncInterval(true); textureCacheGL_->DeviceRestore(draw_); @@ -366,7 +363,6 @@ void GPU_GLES::InitClear() { void GPU_GLES::BeginHostFrame() { GPUCommon::BeginHostFrame(); - UpdateCmdInfo(); if (resized_) { CheckGPUFeatures(); framebufferManager_->Resized(); diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index bb06521ea6..d1e6afb5d6 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -108,21 +108,8 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, queries.push_back({ &u_world, "u_world" }); queries.push_back({ &u_texmtx, "u_texmtx" }); - if (VSID.Bit(VS_BIT_ENABLE_BONES)) - numBones = TranslateNumBones(VSID.Bits(VS_BIT_BONES, 3) + 1); - else - numBones = 0; queries.push_back({ &u_depthRange, "u_depthRange" }); -#ifdef USE_BONE_ARRAY - queries.push_back({ &u_bone, "u_bone" }); -#else - static const char * const boneNames[8] = { "u_bone0", "u_bone1", "u_bone2", "u_bone3", "u_bone4", "u_bone5", "u_bone6", "u_bone7", }; - for (int i = 0; i < 8; i++) { - queries.push_back({ &u_bone[i], boneNames[i] }); - } -#endif - // Lighting, texturing queries.push_back({ &u_ambient, "u_ambient" }); queries.push_back({ &u_matambientalpha, "u_matambientalpha" }); @@ -475,13 +462,6 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) { float f = (float)gstate.getStencilTestRef() * (1.0f / 255.0f); render_->SetUniformF(&u_stencilReplaceValue, 1, &f); } - float bonetemp[16]; - for (int i = 0; i < numBones; i++) { - if (dirty & (DIRTY_BONEMATRIX0 << i)) { - ConvertMatrix4x3To4x4(bonetemp, gstate.boneMatrix + 12 * i); - render_->SetUniformM4x4(&u_bone[i], bonetemp); - } - } if (dirty & DIRTY_SHADERBLEND) { if (u_blendFixA != -1) { @@ -805,7 +785,7 @@ std::string ShaderManagerGLES::DebugGetShaderString(std::string id, DebugShaderT // as sometimes these features might have an effect on the ID bits. #define CACHE_HEADER_MAGIC 0x83277592 -#define CACHE_VERSION 5 +#define CACHE_VERSION 6 struct CacheHeader { uint32_t magic; uint32_t version; diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index 77b94f9cd2..981b63a476 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -72,13 +72,6 @@ public: int u_world; int u_depthRange; // x,y = viewport xscale/xcenter. z,w=clipping minz/maxz (?) -#ifdef USE_BONE_ARRAY - int u_bone; // array, size is numBones -#else - int u_bone[8]; -#endif - int numBones; - // Shader blending. int u_fbotex; int u_blendFixA; diff --git a/GPU/GLES/VertexShaderGeneratorGLES.cpp b/GPU/GLES/VertexShaderGeneratorGLES.cpp index f9de2d312b..239134b46b 100644 --- a/GPU/GLES/VertexShaderGeneratorGLES.cpp +++ b/GPU/GLES/VertexShaderGeneratorGLES.cpp @@ -38,30 +38,6 @@ #define WRITE p+=sprintf -static const char * const boneWeightAttrDecl[9] = { - "#ERROR#", - "attribute mediump float w1;\n", - "attribute mediump vec2 w1;\n", - "attribute mediump vec3 w1;\n", - "attribute mediump vec4 w1;\n", - "attribute mediump vec4 w1;\nattribute mediump float w2;\n", - "attribute mediump vec4 w1;\nattribute mediump vec2 w2;\n", - "attribute mediump vec4 w1;\nattribute mediump vec3 w2;\n", - "attribute mediump vec4 w1, w2;\n", -}; - -static const char * const boneWeightInDecl[9] = { - "#ERROR#", - "in mediump float w1;\n", - "in mediump vec2 w1;\n", - "in mediump vec3 w1;\n", - "in mediump vec4 w1;\n", - "in mediump vec4 w1;\nin mediump float w2;\n", - "in mediump vec4 w1;\nin mediump vec2 w2;\n", - "in mediump vec4 w1;\nin mediump vec3 w2;\n", - "in mediump vec4 w1, w2;\n", -}; - enum DoLightComputation { LIGHT_OFF, LIGHT_SHADE, @@ -105,7 +81,6 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, bool glslES30 = false; const char *varying = "varying"; const char *attribute = "attribute"; - const char * const * boneWeightDecl = boneWeightAttrDecl; const char *texelFetch = NULL; bool highpFog = false; bool highpTexcoord = false; @@ -158,7 +133,6 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, if (glslES30 || gl_extensions.IsCoreContext) { attribute = "in"; varying = "out"; - boneWeightDecl = boneWeightInDecl; } bool isModeThrough = id.Bit(VS_BIT_IS_THROUGH); @@ -182,7 +156,6 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, bool flipNormal = id.Bit(VS_BIT_NORM_REVERSE); int ls0 = id.Bits(VS_BIT_LS0, 2); int ls1 = id.Bits(VS_BIT_LS1, 2); - bool enableBones = id.Bit(VS_BIT_ENABLE_BONES); bool enableLighting = id.Bit(VS_BIT_LIGHTING_ENABLE); int matUpdate = id.Bits(VS_BIT_MATERIAL_UPDATE, 3); @@ -208,16 +181,6 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, } } - int numBoneWeights = 0; - int boneWeightScale = id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2); - if (enableBones) { - numBoneWeights = 1 + id.Bits(VS_BIT_BONES, 3); - WRITE(p, "%s", boneWeightDecl[numBoneWeights]); - *attrMask |= 1 << ATTR_W1; - if (numBoneWeights >= 5) - *attrMask |= 1 << ATTR_W2; - } - if (useHWTransform) WRITE(p, "%s vec3 position;\n", attribute); else @@ -268,17 +231,6 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, WRITE(p, "uniform mediump mat4 u_texmtx;\n"); *uniformMask |= DIRTY_TEXMATRIX; } - if (enableBones) { -#ifdef USE_BONE_ARRAY - WRITE(p, "uniform mediump mat4 u_bone[%i];\n", numBoneWeights); - *uniformMask |= DIRTY_BONE_UNIFORMS; -#else - for (int i = 0; i < numBoneWeights; i++) { - WRITE(p, "uniform mat4 u_bone%i;\n", i); - *uniformMask |= DIRTY_BONEMATRIX0 << i; - } -#endif - } if (doTexture) { WRITE(p, "uniform vec4 u_uvscaleoffset;\n"); *uniformMask |= DIRTY_UVSCALEOFFSET; @@ -485,7 +437,7 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, } } else { // Step 1: World Transform / Skinning - if (!enableBones) { + if (true) { // Hardware tessellation if (doBezier || doSpline) { WRITE(p, " vec3 _pos[16];\n"); @@ -592,81 +544,6 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, else WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n"); } - } else { - static const char *rescale[4] = {"", " * 1.9921875", " * 1.999969482421875", ""}; // 2*127.5f/128.f, 2*32767.5f/32768.f, 1.0f}; - const char *factor = rescale[boneWeightScale]; - - static const char * const boneWeightAttr[8] = { - "w1.x", "w1.y", "w1.z", "w1.w", - "w2.x", "w2.y", "w2.z", "w2.w", - }; - -#if defined(USE_FOR_LOOP) && defined(USE_BONE_ARRAY) - - // To loop through the weights, we unfortunately need to put them in a float array. - // GLSL ES sucks - no way to directly initialize an array! - switch (numBoneWeights) { - case 1: WRITE(p, " float w[1]; w[0] = w1;\n"); break; - case 2: WRITE(p, " float w[2]; w[0] = w1.x; w[1] = w1.y;\n"); break; - case 3: WRITE(p, " float w[3]; w[0] = w1.x; w[1] = w1.y; w[2] = w1.z;\n"); break; - case 4: WRITE(p, " float w[4]; w[0] = w1.x; w[1] = w1.y; w[2] = w1.z; w[3] = w1.w;\n"); break; - case 5: WRITE(p, " float w[5]; w[0] = w1.x; w[1] = w1.y; w[2] = w1.z; w[3] = w1.w; w[4] = w2;\n"); break; - case 6: WRITE(p, " float w[6]; w[0] = w1.x; w[1] = w1.y; w[2] = w1.z; w[3] = w1.w; w[4] = w2.x; w[5] = w2.y;\n"); break; - case 7: WRITE(p, " float w[7]; w[0] = w1.x; w[1] = w1.y; w[2] = w1.z; w[3] = w1.w; w[4] = w2.x; w[5] = w2.y; w[6] = w2.z;\n"); break; - case 8: WRITE(p, " float w[8]; w[0] = w1.x; w[1] = w1.y; w[2] = w1.z; w[3] = w1.w; w[4] = w2.x; w[5] = w2.y; w[6] = w2.z; w[7] = w2.w;\n"); break; - } - - WRITE(p, " mat4 skinMatrix = w[0] * u_bone[0];\n"); - if (numBoneWeights > 1) { - WRITE(p, " for (int i = 1; i < %i; i++) {\n", numBoneWeights); - WRITE(p, " skinMatrix += w[i] * u_bone[i];\n"); - WRITE(p, " }\n"); - } - -#else - -#ifdef USE_BONE_ARRAY - if (numBoneWeights == 1) - WRITE(p, " mat4 skinMatrix = w1 * u_bone[0]"); - else - WRITE(p, " mat4 skinMatrix = w1.x * u_bone[0]"); - for (int i = 1; i < numBoneWeights; i++) { - const char *weightAttr = boneWeightAttr[i]; - // workaround for "cant do .x of scalar" issue - if (numBoneWeights == 1 && i == 0) weightAttr = "w1"; - if (numBoneWeights == 5 && i == 4) weightAttr = "w2"; - WRITE(p, " + %s * u_bone[%i]", weightAttr, i); - } -#else - // Uncomment this to screw up bone shaders to check the vertex shader software fallback - // WRITE(p, "THIS SHOULD ERROR! #error"); - if (numBoneWeights == 1) - WRITE(p, " mat4 skinMatrix = w1 * u_bone0"); - else - WRITE(p, " mat4 skinMatrix = w1.x * u_bone0"); - for (int i = 1; i < numBoneWeights; i++) { - const char *weightAttr = boneWeightAttr[i]; - // workaround for "cant do .x of scalar" issue - if (numBoneWeights == 1 && i == 0) weightAttr = "w1"; - if (numBoneWeights == 5 && i == 4) weightAttr = "w2"; - WRITE(p, " + %s * u_bone%i", weightAttr, i); - } -#endif - -#endif - - WRITE(p, ";\n"); - - // Trying to simplify this results in bugs in LBP... - WRITE(p, " vec3 skinnedpos = (skinMatrix * vec4(position, 1.0)).xyz %s;\n", factor); - WRITE(p, " vec3 worldpos = (u_world * vec4(skinnedpos, 1.0)).xyz;\n"); - - if (hasNormal) { - WRITE(p, " mediump vec3 skinnednormal = (skinMatrix * vec4(%snormal, 0.0)).xyz %s;\n", flipNormal ? "-" : "", factor); - } else { - WRITE(p, " mediump vec3 skinnednormal = (skinMatrix * vec4(0.0, 0.0, %s1.0, 0.0)).xyz %s;\n", flipNormal ? "-" : "", factor); - } - WRITE(p, " mediump vec3 worldnormal = normalize((u_world * vec4(skinnednormal, 0.0)).xyz);\n"); } WRITE(p, " vec4 viewPos = u_view * vec4(worldpos, 1.0);\n"); diff --git a/GPU/GLES/VertexShaderGeneratorGLES.h b/GPU/GLES/VertexShaderGeneratorGLES.h index 7801b2cd6f..ae78cad767 100644 --- a/GPU/GLES/VertexShaderGeneratorGLES.h +++ b/GPU/GLES/VertexShaderGeneratorGLES.h @@ -19,8 +19,6 @@ #include "Common/CommonTypes.h" -// #define USE_BONE_ARRAY - struct VShaderID; void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, uint64_t *uniformMask); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 7640b7e794..2409b85c6b 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -46,8 +46,8 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_BEZIER, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPUCommon::Execute_Bezier }, { GE_CMD_SPLINE, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPUCommon::Execute_Spline }, - // Changing the vertex type requires us to flush. - { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_VertexType }, + // Changing the vertex type does not always require us to flush so handle that in Execute_VertexType. + { GE_CMD_VERTEXTYPE, FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_VertexType }, { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_LoadClut }, @@ -403,23 +403,11 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : ERROR_LOG(G3D, "Command missing from table: %02x (%i)", i, i); } } - - UpdateCmdInfo(); } GPUCommon::~GPUCommon() { } -void GPUCommon::UpdateCmdInfo() { - if (g_Config.bSoftwareSkinning) { - cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexTypeSkinning; - } else { - cmdInfo_[GE_CMD_VERTEXTYPE].flags |= FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexType; - } -} - void GPUCommon::BeginHostFrame() { ReapplyGfxState(); @@ -1425,22 +1413,12 @@ void GPUCommon::Execute_TexSize0(u32 op, u32 diff) { } } -void GPUCommon::Execute_VertexType(u32 op, u32 diff) { - if (diff) - gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); - if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) { - gstate_c.Dirty(DIRTY_UVSCALEOFFSET); - if (diff & GE_VTYPE_THROUGH_MASK) - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE); - } -} - void GPUCommon::Execute_LoadClut(u32 op, u32 diff) { gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); textureCache_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); } -void GPUCommon::Execute_VertexTypeSkinning(u32 op, u32 diff) { +void GPUCommon::Execute_VertexType(u32 op, u32 diff) { // Don't flush when weight count changes. if (diff & ~GE_VTYPE_WEIGHTCOUNT_MASK) { // Restore and flush @@ -1638,10 +1616,6 @@ void GPUCommon::Execute_Bezier(u32 op, u32 diff) { indices = Memory::GetPointerUnchecked(gstate_c.indexAddr); } - if (vertTypeIsSkinningEnabled(gstate.vertType)) { - DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); - } - GEPatchPrimType patchPrim = gstate.getPatchPrimitiveType(); SetDrawType(DRAW_BEZIER, PatchPrimToPrim(patchPrim)); @@ -1700,10 +1674,6 @@ void GPUCommon::Execute_Spline(u32 op, u32 diff) { indices = Memory::GetPointerUnchecked(gstate_c.indexAddr); } - if (vertTypeIsSkinningEnabled(gstate.vertType)) { - DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); - } - int sp_ucount = op & 0xFF; int sp_vcount = (op >> 8) & 0xFF; int sp_utype = (op >> 16) & 0x3; @@ -1984,34 +1954,10 @@ void GPUCommon::Execute_BoneMtxNum(u32 op, u32 diff) { } if (fastLoad) { - // If we can't use software skinning, we have to flush and dirty. - if (!g_Config.bSoftwareSkinning) { - while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) { - const u32 newVal = src[i] << 8; - if (dst[i] != newVal) { - Flush(); - dst[i] = newVal; - } - if (++i >= end) { - break; - } - } - - const unsigned int numPlusCount = (op & 0x7F) + i; - for (unsigned int num = op & 0x7F; num < numPlusCount; num += 12) { - gstate_c.Dirty(DIRTY_BONEMATRIX0 << (num / 12)); - } - } else { - while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) { - dst[i] = src[i] << 8; - if (++i >= end) { - break; - } - } - - const unsigned int numPlusCount = (op & 0x7F) + i; - for (unsigned int num = op & 0x7F; num < numPlusCount; num += 12) { - gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12); + while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) { + dst[i] = src[i] << 8; + if (++i >= end) { + break; } } } @@ -2029,13 +1975,6 @@ void GPUCommon::Execute_BoneMtxData(u32 op, u32 diff) { int num = gstate.boneMatrixNumber & 0x7F; u32 newVal = op << 8; if (num < 96 && newVal != ((const u32 *)gstate.boneMatrix)[num]) { - // Bone matrices should NOT flush when software skinning is enabled! - if (!g_Config.bSoftwareSkinning) { - Flush(); - gstate_c.Dirty(DIRTY_BONEMATRIX0 << (num / 12)); - } else { - gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12); - } ((u32 *)gstate.boneMatrix)[num] = newVal; } num++; @@ -2175,17 +2114,6 @@ void GPUCommon::Execute_Unknown(u32 op, u32 diff) { void GPUCommon::FastLoadBoneMatrix(u32 target) { const int num = gstate.boneMatrixNumber & 0x7F; const int mtxNum = num / 12; - uint32_t uniformsToDirty = DIRTY_BONEMATRIX0 << mtxNum; - if ((num - 12 * mtxNum) != 0) { - uniformsToDirty |= DIRTY_BONEMATRIX0 << ((mtxNum + 1) & 7); - } - - if (!g_Config.bSoftwareSkinning) { - Flush(); - gstate_c.Dirty(uniformsToDirty); - } else { - gstate_c.deferredVertTypeDirty |= uniformsToDirty; - } gstate.FastLoadBoneMatrix(target); } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 5b6b78ce43..52bcec023f 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -72,8 +72,6 @@ public: } virtual void CheckGPUFeatures() = 0; - void UpdateCmdInfo(); - bool IsReady() override { return true; } @@ -131,7 +129,6 @@ public: void Execute_End(u32 op, u32 diff); void Execute_VertexType(u32 op, u32 diff); - void Execute_VertexTypeSkinning(u32 op, u32 diff); void Execute_Prim(u32 op, u32 diff); void Execute_Bezier(u32 op, u32 diff); diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 7e3f3812ef..19ae21706d 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -240,13 +240,6 @@ void GPUgstate::Restore(u32_le *ptr) { } } -bool vertTypeIsSkinningEnabled(u32 vertType) { - if (g_Config.bSoftwareSkinning) - return false; - else - return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE); -} - struct GPUStateCache_v0 { u32 vertexAddr; u32 indexAddr; diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 811f1fa621..aee7cfc579 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -441,8 +441,6 @@ struct GPUgstate { void Restore(u32_le *ptr); }; -bool vertTypeIsSkinningEnabled(u32 vertType); - inline int vertTypeGetNumBoneWeights(u32 vertType) { return 1 + ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); } inline int vertTypeGetWeightMask(u32 vertType) { return vertType & GE_VTYPE_WEIGHT_MASK; } inline int vertTypeGetTexCoordMask(u32 vertType) { return vertType & GE_VTYPE_TC_MASK; } diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index b490659829..39c13a0b71 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -395,10 +395,6 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) { indices = Memory::GetPointerUnchecked(gstate_c.indexAddr); } - if ((gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) || vertTypeIsSkinningEnabled(gstate.vertType)) { - DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); - } - GEPatchPrimType patchPrim = gstate.getPatchPrimitiveType(); SetDrawType(DRAW_BEZIER, PatchPrimToPrim(patchPrim)); @@ -443,10 +439,6 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) { indices = Memory::GetPointerUnchecked(gstate_c.indexAddr); } - if ((gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) || vertTypeIsSkinningEnabled(gstate.vertType)) { - DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); - } - int sp_ucount = op & 0xFF; int sp_vcount = (op >> 8) & 0xFF; int sp_utype = (op >> 16) & 0x3; diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 8f5505aa79..8a3bd02232 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -167,27 +167,6 @@ VertexData TransformUnit::ReadVertex(VertexReader& vreader) vertex.normal = -vertex.normal; } - if (vertTypeIsSkinningEnabled(gstate.vertType) && !gstate.isModeThrough()) { - float W[8] = { 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f }; - vreader.ReadWeights(W); - - Vec3 tmppos(0.f, 0.f, 0.f); - Vec3 tmpnrm(0.f, 0.f, 0.f); - - for (int i = 0; i < vertTypeGetNumBoneWeights(gstate.vertType); ++i) { - Mat3x3 bone(&gstate.boneMatrix[12*i]); - tmppos += (bone * ModelCoords(pos[0], pos[1], pos[2]) + Vec3(gstate.boneMatrix[12*i+9], gstate.boneMatrix[12*i+10], gstate.boneMatrix[12*i+11])) * W[i]; - if (vreader.hasNormal()) - tmpnrm += (bone * vertex.normal) * W[i]; - } - - pos[0] = tmppos.x; - pos[1] = tmppos.y; - pos[2] = tmppos.z; - if (vreader.hasNormal()) - vertex.normal = tmpnrm; - } - if (vreader.hasColor0()) { float col[4]; vreader.ReadColor0(col); diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index faba817b1c..c3acc89267 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -66,8 +66,7 @@ enum { DRAW_BINDING_2ND_TEXTURE = 1, DRAW_BINDING_DYNUBO_BASE = 2, DRAW_BINDING_DYNUBO_LIGHT = 3, - DRAW_BINDING_DYNUBO_BONE = 4, - DRAW_BINDING_TESS_STORAGE_BUF = 5, + DRAW_BINDING_TESS_STORAGE_BUF = 4, }; enum { @@ -95,7 +94,7 @@ DrawEngineVulkan::DrawEngineVulkan(VulkanContext *vulkan, Draw::DrawContext *dra void DrawEngineVulkan::InitDeviceObjects() { // All resources we need for PSP drawing. Usually only bindings 0 and 2-4 are populated. - VkDescriptorSetLayoutBinding bindings[6]{}; + VkDescriptorSetLayoutBinding bindings[5]{}; bindings[0].descriptorCount = 1; bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; bindings[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; @@ -112,15 +111,11 @@ void DrawEngineVulkan::InitDeviceObjects() { bindings[3].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; bindings[3].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; bindings[3].binding = DRAW_BINDING_DYNUBO_LIGHT; - bindings[4].descriptorCount = 1; - bindings[4].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - bindings[4].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - bindings[4].binding = DRAW_BINDING_DYNUBO_BONE; // Used only for hardware tessellation. - bindings[5].descriptorCount = 1; - bindings[5].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - bindings[5].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - bindings[5].binding = DRAW_BINDING_TESS_STORAGE_BUF; + bindings[4].descriptorCount = 1; + bindings[4].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + bindings[4].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + bindings[4].binding = DRAW_BINDING_TESS_STORAGE_BUF; VkDevice device = vulkan_->GetDevice(); @@ -134,7 +129,7 @@ void DrawEngineVulkan::InitDeviceObjects() { // if creating and updating them turns out to be expensive. for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { // We now create descriptor pools on demand, so removed from here. - frame_[i].pushUBO = new VulkanPushBuffer(vulkan_, 8 * 1024 * 1024); + frame_[i].pushUBO = new VulkanPushBuffer(vulkan_, 4 * 1024 * 1024); frame_[i].pushVertex = new VulkanPushBuffer(vulkan_, 2 * 1024 * 1024); frame_[i].pushIndex = new VulkanPushBuffer(vulkan_, 1 * 1024 * 1024); } @@ -364,7 +359,7 @@ VkResult DrawEngineVulkan::RecreateDescriptorPool(FrameData &frame, int newSize) frame.descPoolSize = newSize; VkDescriptorPoolSize dpTypes[3]; - dpTypes[0].descriptorCount = frame.descPoolSize * 3; + dpTypes[0].descriptorCount = frame.descPoolSize * 2; dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; dpTypes[1].descriptorCount = frame.descPoolSize * 2; // Don't use these for tess anymore, need max two per set. dpTypes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; @@ -382,17 +377,15 @@ VkResult DrawEngineVulkan::RecreateDescriptorPool(FrameData &frame, int newSize) return res; } -VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView, VkSampler sampler, VkBuffer base, VkBuffer light, VkBuffer bone, bool tess) { +VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView, VkSampler sampler, VkBuffer base, VkBuffer light, bool tess) { DescriptorSetKey key; key.imageView_ = imageView; key.sampler_ = sampler; key.secondaryImageView_ = boundSecondary_; key.base_ = base; key.light_ = light; - key.bone_ = bone; _dbg_assert_(G3D, base != VK_NULL_HANDLE); _dbg_assert_(G3D, light != VK_NULL_HANDLE); - _dbg_assert_(G3D, bone != VK_NULL_HANDLE); FrameData &frame = frame_[vulkan_->GetCurFrame()]; // See if we already have this descriptor set cached. @@ -494,7 +487,7 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView } // Uniform buffer objects - VkDescriptorBufferInfo buf[3]{}; + VkDescriptorBufferInfo buf[2]{}; int count = 0; buf[count].buffer = base; buf[count].offset = 0; @@ -504,10 +497,6 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView buf[count].offset = 0; buf[count].range = sizeof(UB_VS_Lights); count++; - buf[count].buffer = bone; - buf[count].offset = 0; - buf[count].range = sizeof(UB_VS_Bones); - count++; for (int i = 0; i < count; i++) { writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writes[n].pNext = nullptr; @@ -531,11 +520,9 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView void DrawEngineVulkan::DirtyAllUBOs() { baseUBOOffset = 0; lightUBOOffset = 0; - boneUBOOffset = 0; baseBuf = VK_NULL_HANDLE; lightBuf = VK_NULL_HANDLE; - boneBuf = VK_NULL_HANDLE; - dirtyUniforms_ = DIRTY_BASE_UNIFORMS | DIRTY_LIGHT_UNIFORMS | DIRTY_BONE_UNIFORMS; + dirtyUniforms_ = DIRTY_BASE_UNIFORMS | DIRTY_LIGHT_UNIFORMS; imageView = VK_NULL_HANDLE; sampler = VK_NULL_HANDLE; gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); @@ -594,7 +581,7 @@ void DrawEngineVulkan::DoFlush() { // Also avoid caching when software skinning. VkBuffer vbuf = VK_NULL_HANDLE; VkBuffer ibuf = VK_NULL_HANDLE; - if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { + if (lastVType_ & GE_VTYPE_WEIGHT_MASK) { useCache = false; } @@ -736,7 +723,7 @@ void DrawEngineVulkan::DoFlush() { break; } } else { - if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { + if (lastVType_ & GE_VTYPE_WEIGHT_MASK) { // If software skinning, we've already predecoded into "decoded". So push that content. VkDeviceSize size = decodedVerts_ * dec_->GetDecVtxFmt().stride; u8 *dest = (u8 *)frame->pushVertex->Push(size, &vbOffset, &vbuf); @@ -808,12 +795,12 @@ void DrawEngineVulkan::DoFlush() { dirtyUniforms_ |= shaderManager_->UpdateUniforms(); UpdateUBOs(frame); - VkDescriptorSet ds = GetOrCreateDescriptorSet(imageView, sampler, baseBuf, lightBuf, boneBuf, tess); + VkDescriptorSet ds = GetOrCreateDescriptorSet(imageView, sampler, baseBuf, lightBuf, tess); { PROFILE_THIS_SCOPE("renderman_q"); - const uint32_t dynamicUBOOffsets[3] = { - baseUBOOffset, lightUBOOffset, boneUBOOffset, + const uint32_t dynamicUBOOffsets[2] = { + baseUBOOffset, lightUBOOffset, }; int stride = dec_->GetDecVtxFmt().stride; @@ -914,9 +901,9 @@ void DrawEngineVulkan::DoFlush() { // Even if the first draw is through-mode, make sure we at least have one copy of these uniforms buffered UpdateUBOs(frame); - VkDescriptorSet ds = GetOrCreateDescriptorSet(imageView, sampler, baseBuf, lightBuf, boneBuf, tess); - const uint32_t dynamicUBOOffsets[3] = { - baseUBOOffset, lightUBOOffset, boneUBOOffset, + VkDescriptorSet ds = GetOrCreateDescriptorSet(imageView, sampler, baseBuf, lightBuf, tess); + const uint32_t dynamicUBOOffsets[2] = { + baseUBOOffset, lightUBOOffset, }; PROFILE_THIS_SCOPE("renderman_q"); @@ -983,10 +970,6 @@ void DrawEngineVulkan::UpdateUBOs(FrameData *frame) { lightUBOOffset = shaderManager_->PushLightBuffer(frame->pushUBO, &lightBuf); dirtyUniforms_ &= ~DIRTY_LIGHT_UNIFORMS; } - if ((dirtyUniforms_ & DIRTY_BONE_UNIFORMS) || boneBuf == VK_NULL_HANDLE) { - boneUBOOffset = shaderManager_->PushBoneBuffer(frame->pushUBO, &boneBuf); - dirtyUniforms_ &= ~DIRTY_BONE_UNIFORMS; - } } DrawEngineVulkan::TessellationDataTransferVulkan::TessellationDataTransferVulkan(VulkanContext *vulkan, Draw::DrawContext *draw) diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index d39186837c..8b58dbb868 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -23,7 +23,7 @@ // * binding 1: Secondary texture sampler for shader blending or depal palettes // * binding 2: Base Uniform Buffer (includes fragment state) // * binding 3: Light uniform buffer -// * binding 4: Bone uniform buffer +// * binding 4: Shader buffer storage for tesselation // // All shaders conform to this layout, so they are all compatible with the same descriptor set. // The format of the various uniform buffers may vary though - vertex shaders that don't skin @@ -195,7 +195,7 @@ private: void DoFlush(); void UpdateUBOs(FrameData *frame); - VkDescriptorSet GetOrCreateDescriptorSet(VkImageView imageView, VkSampler sampler, VkBuffer base, VkBuffer light, VkBuffer bone, bool tess); + VkDescriptorSet GetOrCreateDescriptorSet(VkImageView imageView, VkSampler sampler, VkBuffer base, VkBuffer light, bool tess); VulkanContext *vulkan_; Draw::DrawContext *draw_; @@ -219,7 +219,7 @@ private: VkImageView imageView_; VkImageView secondaryImageView_; VkSampler sampler_; - VkBuffer base_, light_, bone_; // All three UBO slots will be set to this. This will usually be identical + VkBuffer base_, light_; // All three UBO slots will be set to this. This will usually be identical // for all draws in a frame, except when the buffer has to grow. }; @@ -253,8 +253,7 @@ private: uint64_t dirtyUniforms_; uint32_t baseUBOOffset; uint32_t lightUBOOffset; - uint32_t boneUBOOffset; - VkBuffer baseBuf, lightBuf, boneBuf; + VkBuffer baseBuf, lightBuf; VkImageView imageView = VK_NULL_HANDLE; VkSampler sampler = VK_NULL_HANDLE; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 0aeefe8495..f4b1731777 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -190,7 +190,6 @@ void GPU_Vulkan::CheckGPUFeatures() { void GPU_Vulkan::BeginHostFrame() { drawEngine_.BeginFrame(); - UpdateCmdInfo(); if (resized_) { CheckGPUFeatures(); @@ -425,7 +424,6 @@ void GPU_Vulkan::DeviceRestore() { CheckGPUFeatures(); BuildReportingInfo(); - UpdateCmdInfo(); framebufferManagerVulkan_->DeviceRestore(vulkan_, draw_); vulkan2D_.DeviceRestore(vulkan_); diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index eabd8a1827..06aa2ef80a 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -292,9 +292,6 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip if (vs->HasLights()) { vulkanPipeline->uniformBlocks |= UB_VS_LIGHTS; } - if (vs->HasBones()) { - vulkanPipeline->uniformBlocks |= UB_VS_BONES; - } } return vulkanPipeline; } diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index 8463033784..846f9d84da 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -56,8 +56,7 @@ struct VulkanPipelineKey { enum { UB_VS_FS_BASE = (1 << 0), - UB_VS_BONES = (1 << 1), - UB_VS_LIGHTS = (1 << 2), + UB_VS_LIGHTS = (1 << 1), }; // Simply wraps a Vulkan pipeline, providing some metadata. diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index bc6e467b7a..4131a24047 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -158,11 +158,9 @@ ShaderManagerVulkan::ShaderManagerVulkan(VulkanContext *vulkan) uboAlignment_ = vulkan_->GetPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment; memset(&ub_base, 0, sizeof(ub_base)); memset(&ub_lights, 0, sizeof(ub_lights)); - memset(&ub_bones, 0, sizeof(ub_bones)); ILOG("sizeof(ub_base): %d", (int)sizeof(ub_base)); ILOG("sizeof(ub_lights): %d", (int)sizeof(ub_lights)); - ILOG("sizeof(ub_bones): %d", (int)sizeof(ub_bones)); } ShaderManagerVulkan::~ShaderManagerVulkan() { @@ -215,8 +213,6 @@ uint64_t ShaderManagerVulkan::UpdateUniforms() { BaseUpdateUniforms(&ub_base, dirty, false); if (dirty & DIRTY_LIGHT_UNIFORMS) LightUpdateUniforms(&ub_lights, dirty); - if (dirty & DIRTY_BONE_UNIFORMS) - BoneUpdateUniforms(&ub_bones, dirty); } gstate_c.CleanUniforms(); return dirty; diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index 0078b5cba5..b8593d5d3a 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -63,9 +63,6 @@ public: bool Failed() const { return failed_; } bool UseHWTransform() const { return useHWTransform_; } - bool HasBones() const { - return id_.Bit(VS_BIT_ENABLE_BONES); - } bool HasLights() const { return usesLighting_; } @@ -110,7 +107,6 @@ public: // Applies dirty changes and copies the buffer. bool IsBaseDirty() { return true; } bool IsLightDirty() { return true; } - bool IsBoneDirty() { return true; } uint32_t PushBaseBuffer(VulkanPushBuffer *dest, VkBuffer *buf) { return dest->PushAligned(&ub_base, sizeof(ub_base), uboAlignment_, buf); @@ -118,10 +114,6 @@ public: uint32_t PushLightBuffer(VulkanPushBuffer *dest, VkBuffer *buf) { return dest->PushAligned(&ub_lights, sizeof(ub_lights), uboAlignment_, buf); } - // TODO: Only push half the bone buffer if we only have four bones. - uint32_t PushBoneBuffer(VulkanPushBuffer *dest, VkBuffer *buf) { - return dest->PushAligned(&ub_bones, sizeof(ub_bones), uboAlignment_, buf); - } private: void Clear(); @@ -140,7 +132,6 @@ private: // Uniform block scratchpad. These (the relevant ones) are copied to the current pushbuffer at draw time. UB_VS_FS_Base ub_base; UB_VS_Lights ub_lights; - UB_VS_Bones ub_bones; VulkanFragmentShader *lastFShader_; VulkanVertexShader *lastVShader_; diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp index 8aa8b1719f..a2e00e55d6 100644 --- a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp @@ -54,18 +54,6 @@ static const char *vulkan_glsl_preamble = #define WRITE p+=sprintf -static const char * const boneWeightDecl[9] = { - "#ERROR#", - "layout(location = 3) in float w1;\n", - "layout(location = 3) in vec2 w1;\n", - "layout(location = 3) in vec3 w1;\n", - "layout(location = 3) in vec4 w1;\n", - "layout(location = 3) in vec4 w1;\nlayout(location = 4) in float w2;\n", - "layout(location = 3) in vec4 w1;\nlayout(location = 4) in vec2 w2;\n", - "layout(location = 3) in vec4 w1;\nlayout(location = 4) in vec3 w2;\n", - "layout(location = 3) in vec4 w1;\nlayout(location = 4) in vec4 w2;\n", -}; - enum DoLightComputation { LIGHT_OFF, LIGHT_SHADE, @@ -126,7 +114,6 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *use bool flipNormal = id.Bit(VS_BIT_NORM_REVERSE); int ls0 = id.Bits(VS_BIT_LS0, 2); int ls1 = id.Bits(VS_BIT_LS1, 2); - bool enableBones = id.Bit(VS_BIT_ENABLE_BONES); bool enableLighting = id.Bit(VS_BIT_LIGHTING_ENABLE); int matUpdate = id.Bits(VS_BIT_MATERIAL_UPDATE, 3); @@ -144,8 +131,6 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *use WRITE(p, "layout (std140, set = 0, binding = 2) uniform baseVars {\n%s} base;\n", ub_baseStr); if (enableLighting || doShadeMapping) WRITE(p, "layout (std140, set = 0, binding = 3) uniform lightVars {\n%s} light;\n", ub_vs_lightsStr); - if (enableBones) - WRITE(p, "layout (std140, set = 0, binding = 4) uniform boneVars {\n%s} bone;\n", ub_vs_bonesStr); const char *shading = doFlatShading ? "flat " : ""; @@ -161,13 +146,6 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *use } } - int numBoneWeights = 0; - int boneWeightScale = id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2); - if (enableBones) { - numBoneWeights = 1 + id.Bits(VS_BIT_BONES, 3); - WRITE(p, "%s", boneWeightDecl[numBoneWeights]); - } - if (useHWTransform) WRITE(p, "layout (location = %d) in vec3 position;\n", (int)PspAttributeLocation::POSITION); else @@ -333,7 +311,7 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *use } } else { // Step 1: World Transform / Skinning - if (!enableBones) { + if (true) { if (doBezier || doSpline) { WRITE(p, " vec3 _pos[16];\n"); WRITE(p, " vec2 _tex[16];\n"); @@ -439,34 +417,6 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *use else WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n"); } - } else { - static const char *rescale[4] = { "", " * 1.9921875", " * 1.999969482421875", "" }; // 2*127.5f/128.f, 2*32767.5f/32768.f, 1.0f}; - const char *factor = rescale[boneWeightScale]; - - static const char * const boneWeightAttr[8] = { - "w1.x", "w1.y", "w1.z", "w1.w", - "w2.x", "w2.y", "w2.z", "w2.w", - }; - - WRITE(p, " mat3x4 skinMatrix = w1.x * bone.m[0];\n"); - if (numBoneWeights > 1) { - for (int i = 1; i < numBoneWeights; i++) { - WRITE(p, " skinMatrix += %s * bone.m[%i];\n", boneWeightAttr[i], i); - } - } - - WRITE(p, ";\n"); - - // Trying to simplify this results in bugs in LBP... - WRITE(p, " vec3 skinnedpos = (vec4(position, 1.0) * skinMatrix) %s;\n", factor); - WRITE(p, " vec3 worldpos = vec4(skinnedpos, 1.0) * base.world_mtx;\n"); - - if (hasNormal) { - WRITE(p, " mediump vec3 skinnednormal = vec4(%snormal, 0.0) * skinMatrix %s;\n", flipNormal ? "-" : "", factor); - } else { - WRITE(p, " mediump vec3 skinnednormal = vec4(0.0, 0.0, %s1.0, 0.0) * skinMatrix %s;\n", flipNormal ? "-" : "", factor); - } - WRITE(p, " mediump vec3 worldnormal = normalize(vec4(skinnednormal, 0.0) * base.world_mtx);\n"); } WRITE(p, " vec4 viewPos = vec4(vec4(worldpos, 1.0) * base.view_mtx, 1.0);\n"); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index c42427622c..5b3e4a2705 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -298,13 +298,6 @@ void GameSettingsScreen::CreateViews() { hwTransform->OnClick.Handle(this, &GameSettingsScreen::OnHardwareTransform); hwTransform->SetDisabledPtr(&g_Config.bSoftwareRendering); - CheckBox *swSkin = graphicsSettings->Add(new CheckBox(&g_Config.bSoftwareSkinning, gr->T("Software Skinning"))); - swSkin->OnClick.Add([=](EventParams &e) { - settingInfo_->Show(gr->T("SoftwareSkinning Tip", "Combine skinned model draws on the CPU, faster in most games"), e.v); - return UI::EVENT_CONTINUE; - }); - swSkin->SetDisabledPtr(&g_Config.bSoftwareRendering); - CheckBox *vtxCache = graphicsSettings->Add(new CheckBox(&g_Config.bVertexCache, gr->T("Vertex Cache"))); vtxCache->OnClick.Add([=](EventParams &e) { settingInfo_->Show(gr->T("VertexCache Tip", "Faster, but may cause temporary flicker"), e.v); diff --git a/ext/native/thin3d/VulkanQueueRunner.h b/ext/native/thin3d/VulkanQueueRunner.h index b52b150fa3..807d1e47e8 100644 --- a/ext/native/thin3d/VulkanQueueRunner.h +++ b/ext/native/thin3d/VulkanQueueRunner.h @@ -41,7 +41,7 @@ struct VkRenderData { VkPipelineLayout pipelineLayout; VkDescriptorSet ds; int numUboOffsets; - uint32_t uboOffsets[3]; + uint32_t uboOffsets[2]; VkBuffer vbuffer; // might need to increase at some point VkDeviceSize voffset; VkBuffer ibuffer; diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 661211d1d0..883f608537 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -369,7 +369,6 @@ int main(int argc, const char* argv[]) g_Config.bFrameSkipUnthrottle = false; g_Config.bEnableLogging = fullLog; g_Config.iNumWorkerThreads = 1; - g_Config.bSoftwareSkinning = true; g_Config.bVertexDecoderJit = true; g_Config.bBlockTransferGPU = true; g_Config.iSplineBezierQuality = 2; diff --git a/unittest/TestVertexJit.cpp b/unittest/TestVertexJit.cpp index 40dd640c8b..dc964c4564 100644 --- a/unittest/TestVertexJit.cpp +++ b/unittest/TestVertexJit.cpp @@ -543,7 +543,6 @@ static bool TestVertexColor565() { static bool TestVertex8Skin() { VertexDecoderTestHarness dec; - g_Config.bSoftwareSkinning = true; for (int i = 0; i < 8 * 12; ++i) { gstate.boneMatrix[i] = 0.0f; } @@ -573,7 +572,6 @@ static bool TestVertex8Skin() { static bool TestVertex16Skin() { VertexDecoderTestHarness dec; - g_Config.bSoftwareSkinning = true; for (int i = 0; i < 8 * 12; ++i) { gstate.boneMatrix[i] = 0.0f; } @@ -603,7 +601,6 @@ static bool TestVertex16Skin() { static bool TestVertexFloatSkin() { VertexDecoderTestHarness dec; - g_Config.bSoftwareSkinning = true; for (int i = 0; i < 8 * 12; ++i) { gstate.boneMatrix[i] = 0.0f; } From fcdb816235d46e582f797e41d7ee344c81194cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 2 Mar 2018 14:52:44 +0100 Subject: [PATCH 227/291] Remove gstate_c.deferredVertTypeDirty --- GPU/GPUCommon.cpp | 6 ------ GPU/GPUState.h | 1 - 2 files changed, 7 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 2409b85c6b..d128baa857 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1427,12 +1427,6 @@ void GPUCommon::Execute_VertexType(u32 op, u32 diff) { gstate.vertType ^= diff; if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) gstate_c.Dirty(DIRTY_UVSCALEOFFSET); - // In this case, we may be doing weights and morphs. - // Update any bone matrix uniforms so it uses them correctly. - if ((op & GE_VTYPE_MORPHCOUNT_MASK) != 0) { - gstate_c.Dirty(gstate_c.deferredVertTypeDirty); - gstate_c.deferredVertTypeDirty = 0; - } gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); } if (diff & GE_VTYPE_THROUGH_MASK) diff --git a/GPU/GPUState.h b/GPU/GPUState.h index aee7cfc579..18d43d0691 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -557,7 +557,6 @@ struct GPUStateCache { bool allowShaderBlend; float morphWeights[8]; - u32 deferredVertTypeDirty; u32 curTextureWidth; u32 curTextureHeight; From 6fa9fcefb2893d1e9f3250337aa4f8243b6e3b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 2 Mar 2018 14:57:35 +0100 Subject: [PATCH 228/291] Comment fixes, reindentation. --- GPU/Common/DrawEngineCommon.h | 2 +- GPU/Common/VertexDecoderCommon.cpp | 9 +- GPU/Common/VertexDecoderCommon.h | 3 - GPU/D3D11/DrawEngineD3D11.cpp | 2 +- GPU/Directx9/DrawEngineDX9.cpp | 2 +- GPU/Directx9/VertexShaderGeneratorDX9.cpp | 213 ++++++++++----------- GPU/GLES/DrawEngineGLES.cpp | 50 +---- GPU/GLES/VertexShaderGeneratorGLES.cpp | 211 ++++++++++---------- GPU/Vulkan/DrawEngineVulkan.cpp | 4 +- GPU/Vulkan/VertexShaderGeneratorVulkan.cpp | 207 ++++++++++---------- 10 files changed, 319 insertions(+), 384 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index c4af21114b..0bf9a30525 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -126,7 +126,7 @@ protected: TransformedVertex *transformed = nullptr; TransformedVertex *transformedExpanded = nullptr; - // Defer all vertex decoding to a "Flush" (except when software skinning) + // Defer all vertex decoding to a "Flush" (except when skinning) struct DeferredDrawCall { void *verts; void *inds; diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index af3f63d5a7..bedd9c9186 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -41,7 +41,7 @@ static const u8 nrmsize[4] = { 0, 3, 6, 12 }, nrmalign[4] = { 0, 1, 2, 4 }; static const u8 possize[4] = { 3, 3, 6, 12 }, posalign[4] = { 1, 1, 2, 4 }; static const u8 wtsize[4] = { 0, 1, 2, 4 }, wtalign[4] = { 0, 1, 2, 4 }; -// When software skinning. This array is only used when non-jitted - when jitted, the matrix +// This array is only used when non-jitted - when jitted, the matrix // is kept in registers. alignas(16) static float skinMatrix[12]; @@ -49,13 +49,6 @@ inline int align(int n, int align) { return (n + (align - 1)) & ~(align - 1); } -int TranslateNumBones(int bones) { - if (!bones) return 0; - if (bones < 4) return 4; - // if (bones < 8) return 8; I get drawing problems in FF:CC with this! - return bones; -} - int DecFmtSize(u8 fmt) { switch (fmt) { case DEC_NONE: return 0; diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index d5395704f1..17efcabb32 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -431,9 +431,6 @@ struct JitLookup { JitStepFunction jitFunc; }; -// Collapse to less skinning shaders to reduce shader switching, which is expensive. -int TranslateNumBones(int bones); - typedef void(*JittedVertexDecoder)(const u8 *src, u8 *dst, int count); struct VertexDecoderOptions { diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 55006baca7..29273e04a2 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -343,7 +343,7 @@ void DrawEngineD3D11::DoFlush() { // Cannot cache vertex data with morph enabled. bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); - // Also avoid caching when software skinning. + // Also avoid caching when skinning. if (lastVType_ & GE_VTYPE_WEIGHT_MASK) useCache = false; diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 9330893a97..99ee183863 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -324,7 +324,7 @@ void DrawEngineDX9::DoFlush() { // Cannot cache vertex data with morph enabled. bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); - // Also avoid caching when software skinning. + // Also avoid caching when skinning. if (lastVType_ & GE_VTYPE_WEIGHT_MASK) useCache = false; diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.cpp b/GPU/Directx9/VertexShaderGeneratorDX9.cpp index 8c37144401..b3d35fc478 100644 --- a/GPU/Directx9/VertexShaderGeneratorDX9.cpp +++ b/GPU/Directx9/VertexShaderGeneratorDX9.cpp @@ -358,116 +358,113 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage } } } else { - // Step 1: World Transform / Skinning - if (true) { - // Hardware tessellation - if (doSpline || doBezier) { - WRITE(p, " uint num_patches_u = %s;\n", doBezier ? "(u_spline_count_u - 1) / 3u" : "u_spline_count_u - 3"); - WRITE(p, " float2 tess_pos = In.position.xy;\n"); - WRITE(p, " int u = In.instanceId %% num_patches_u;\n"); - WRITE(p, " int v = In.instanceId / num_patches_u;\n"); - WRITE(p, " int2 patch_pos = int2(u, v);\n"); - WRITE(p, " float3 _pos[16];\n"); - WRITE(p, " float2 _tex[16];\n"); - WRITE(p, " float4 _col[16];\n"); - WRITE(p, " int idx;\n"); - WRITE(p, " int2 index;\n"); - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - WRITE(p, " idx = (%i + v%s) * u_spline_count_u + (%i + u%s);\n", i, doBezier ? " * 3" : "", j, doBezier ? " * 3" : ""); - WRITE(p, " index = int2(idx, 0);\n"); - WRITE(p, " _pos[%i] = u_tess_pos_tex.Load(index).xyz;\n", i * 4 + j); - if (doTexture && hasTexcoord && hasTexcoordTess) - WRITE(p, " _tex[%i] = u_tess_tex_tex.Load(index).xy;\n", i * 4 + j); - if (hasColor && hasColorTess) - WRITE(p, " _col[%i] = u_tess_col_tex.Load(index).rgba;\n", i * 4 + j); - } + // Step 1: World Transform + // Hardware tessellation + if (doSpline || doBezier) { + WRITE(p, " uint num_patches_u = %s;\n", doBezier ? "(u_spline_count_u - 1) / 3u" : "u_spline_count_u - 3"); + WRITE(p, " float2 tess_pos = In.position.xy;\n"); + WRITE(p, " int u = In.instanceId %% num_patches_u;\n"); + WRITE(p, " int v = In.instanceId / num_patches_u;\n"); + WRITE(p, " int2 patch_pos = int2(u, v);\n"); + WRITE(p, " float3 _pos[16];\n"); + WRITE(p, " float2 _tex[16];\n"); + WRITE(p, " float4 _col[16];\n"); + WRITE(p, " int idx;\n"); + WRITE(p, " int2 index;\n"); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + WRITE(p, " idx = (%i + v%s) * u_spline_count_u + (%i + u%s);\n", i, doBezier ? " * 3" : "", j, doBezier ? " * 3" : ""); + WRITE(p, " index = int2(idx, 0);\n"); + WRITE(p, " _pos[%i] = u_tess_pos_tex.Load(index).xyz;\n", i * 4 + j); + if (doTexture && hasTexcoord && hasTexcoordTess) + WRITE(p, " _tex[%i] = u_tess_tex_tex.Load(index).xy;\n", i * 4 + j); + if (hasColor && hasColorTess) + WRITE(p, " _col[%i] = u_tess_col_tex.Load(index).rgba;\n", i * 4 + j); } - WRITE(p, " float2 weights[4];\n"); - if (doBezier) { - // Bernstein 3D - WRITE(p, " weights[0] = (1.0 - tess_pos) * (1.0 - tess_pos) * (1.0 - tess_pos);\n"); - WRITE(p, " weights[1] = 3.0 * tess_pos * (1.0 - tess_pos) * (1.0 - tess_pos);\n"); - WRITE(p, " weights[2] = 3.0 * tess_pos * tess_pos * (1.0 - tess_pos);\n"); - WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n"); - } else if (doSpline) { - WRITE(p, " int2 spline_num_patches = int2(u_spline_count_u - 3, u_spline_count_v - 3);\n"); - WRITE(p, " int2 spline_type = int2(u_spline_type_u, u_spline_type_v);\n"); - WRITE(p, " float2 knots[6];\n"); - WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n"); - WRITE(p, " spline_weight(tess_pos + patch_pos, knots, weights);\n"); - } - WRITE(p, " float3 pos = tess_sample(_pos, weights);\n"); - if (doTexture && hasTexcoord) { - if (hasTexcoordTess) - WRITE(p, " float2 tex = tess_sample(_tex, weights);\n"); - else - WRITE(p, " float2 tex = tess_pos + patch_pos;\n"); - } - if (hasColor) { - if (hasColorTess) - WRITE(p, " float4 col = tess_sample(_col, weights);\n"); - else - WRITE(p, " float4 col = u_tess_col_tex.Load(int2(0, 0)).rgba;\n"); - } - if (hasNormal) { - // Curved surface is probably always need to compute normal(not sampling from control points) - if (doBezier) { - // Bernstein derivative - WRITE(p, " float2 bernderiv[4];\n"); - WRITE(p, " bernderiv[0] = -3.0 * (tess_pos - 1.0) * (tess_pos - 1.0); \n"); - WRITE(p, " bernderiv[1] = 9.0 * tess_pos * tess_pos - 12.0 * tess_pos + 3.0; \n"); - WRITE(p, " bernderiv[2] = 3.0 * (2.0 - 3.0 * tess_pos) * tess_pos; \n"); - WRITE(p, " bernderiv[3] = 3.0 * tess_pos * tess_pos; \n"); - - WRITE(p, " float2 bernderiv_u[4];\n"); - WRITE(p, " float2 bernderiv_v[4];\n"); - WRITE(p, " for (int i = 0; i < 4; i++) {\n"); - WRITE(p, " bernderiv_u[i] = float2(bernderiv[i].x, weights[i].y);\n"); - WRITE(p, " bernderiv_v[i] = float2(weights[i].x, bernderiv[i].y);\n"); - WRITE(p, " }\n"); - - WRITE(p, " float3 du = tess_sample(_pos, bernderiv_u);\n"); - WRITE(p, " float3 dv = tess_sample(_pos, bernderiv_v);\n"); - } else if (doSpline) { - WRITE(p, " float2 tess_next_u = float2(In.normal.x, 0.0);\n"); - WRITE(p, " float2 tess_next_v = float2(0.0, In.normal.y);\n"); - // Right - WRITE(p, " float2 tess_pos_r = tess_pos + tess_next_u;\n"); - WRITE(p, " spline_weight(tess_pos_r + patch_pos, knots, weights);\n"); - WRITE(p, " float3 pos_r = tess_sample(_pos, weights);\n"); - // Left - WRITE(p, " float2 tess_pos_l = tess_pos - tess_next_u;\n"); - WRITE(p, " spline_weight(tess_pos_l + patch_pos, knots, weights);\n"); - WRITE(p, " float3 pos_l = tess_sample(_pos, weights);\n"); - // Down - WRITE(p, " float2 tess_pos_d = tess_pos + tess_next_v;\n"); - WRITE(p, " spline_weight(tess_pos_d + patch_pos, knots, weights);\n"); - WRITE(p, " float3 pos_d = tess_sample(_pos, weights);\n"); - // Up - WRITE(p, " float2 tess_pos_u = tess_pos - tess_next_v;\n"); - WRITE(p, " spline_weight(tess_pos_u + patch_pos, knots, weights);\n"); - WRITE(p, " float3 pos_u = tess_sample(_pos, weights);\n"); - - WRITE(p, " float3 du = pos_r - pos_l;\n"); - WRITE(p, " float3 dv = pos_d - pos_u;\n"); - } - WRITE(p, " float3 nrm = cross(du, dv);\n"); - WRITE(p, " nrm = normalize(nrm);\n"); - } - WRITE(p, " float3 worldpos = mul(float4(pos.xyz, 1.0), u_world);\n"); - if (hasNormal) - WRITE(p, " float3 worldnormal = normalize(mul(float4(%snrm, 0.0), u_world));\n", flipNormalTess ? "-" : ""); - else - WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n"); - } else { - // No skinning, just standard T&L. - WRITE(p, " float3 worldpos = mul(float4(In.position.xyz, 1.0), u_world);\n"); - if (hasNormal) - WRITE(p, " float3 worldnormal = normalize(mul(float4(%sIn.normal, 0.0), u_world));\n", flipNormal ? "-" : ""); - else - WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n"); } + WRITE(p, " float2 weights[4];\n"); + if (doBezier) { + // Bernstein 3D + WRITE(p, " weights[0] = (1.0 - tess_pos) * (1.0 - tess_pos) * (1.0 - tess_pos);\n"); + WRITE(p, " weights[1] = 3.0 * tess_pos * (1.0 - tess_pos) * (1.0 - tess_pos);\n"); + WRITE(p, " weights[2] = 3.0 * tess_pos * tess_pos * (1.0 - tess_pos);\n"); + WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n"); + } else if (doSpline) { + WRITE(p, " int2 spline_num_patches = int2(u_spline_count_u - 3, u_spline_count_v - 3);\n"); + WRITE(p, " int2 spline_type = int2(u_spline_type_u, u_spline_type_v);\n"); + WRITE(p, " float2 knots[6];\n"); + WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n"); + WRITE(p, " spline_weight(tess_pos + patch_pos, knots, weights);\n"); + } + WRITE(p, " float3 pos = tess_sample(_pos, weights);\n"); + if (doTexture && hasTexcoord) { + if (hasTexcoordTess) + WRITE(p, " float2 tex = tess_sample(_tex, weights);\n"); + else + WRITE(p, " float2 tex = tess_pos + patch_pos;\n"); + } + if (hasColor) { + if (hasColorTess) + WRITE(p, " float4 col = tess_sample(_col, weights);\n"); + else + WRITE(p, " float4 col = u_tess_col_tex.Load(int2(0, 0)).rgba;\n"); + } + if (hasNormal) { + // Curved surface is probably always need to compute normal(not sampling from control points) + if (doBezier) { + // Bernstein derivative + WRITE(p, " float2 bernderiv[4];\n"); + WRITE(p, " bernderiv[0] = -3.0 * (tess_pos - 1.0) * (tess_pos - 1.0); \n"); + WRITE(p, " bernderiv[1] = 9.0 * tess_pos * tess_pos - 12.0 * tess_pos + 3.0; \n"); + WRITE(p, " bernderiv[2] = 3.0 * (2.0 - 3.0 * tess_pos) * tess_pos; \n"); + WRITE(p, " bernderiv[3] = 3.0 * tess_pos * tess_pos; \n"); + + WRITE(p, " float2 bernderiv_u[4];\n"); + WRITE(p, " float2 bernderiv_v[4];\n"); + WRITE(p, " for (int i = 0; i < 4; i++) {\n"); + WRITE(p, " bernderiv_u[i] = float2(bernderiv[i].x, weights[i].y);\n"); + WRITE(p, " bernderiv_v[i] = float2(weights[i].x, bernderiv[i].y);\n"); + WRITE(p, " }\n"); + + WRITE(p, " float3 du = tess_sample(_pos, bernderiv_u);\n"); + WRITE(p, " float3 dv = tess_sample(_pos, bernderiv_v);\n"); + } else if (doSpline) { + WRITE(p, " float2 tess_next_u = float2(In.normal.x, 0.0);\n"); + WRITE(p, " float2 tess_next_v = float2(0.0, In.normal.y);\n"); + // Right + WRITE(p, " float2 tess_pos_r = tess_pos + tess_next_u;\n"); + WRITE(p, " spline_weight(tess_pos_r + patch_pos, knots, weights);\n"); + WRITE(p, " float3 pos_r = tess_sample(_pos, weights);\n"); + // Left + WRITE(p, " float2 tess_pos_l = tess_pos - tess_next_u;\n"); + WRITE(p, " spline_weight(tess_pos_l + patch_pos, knots, weights);\n"); + WRITE(p, " float3 pos_l = tess_sample(_pos, weights);\n"); + // Down + WRITE(p, " float2 tess_pos_d = tess_pos + tess_next_v;\n"); + WRITE(p, " spline_weight(tess_pos_d + patch_pos, knots, weights);\n"); + WRITE(p, " float3 pos_d = tess_sample(_pos, weights);\n"); + // Up + WRITE(p, " float2 tess_pos_u = tess_pos - tess_next_v;\n"); + WRITE(p, " spline_weight(tess_pos_u + patch_pos, knots, weights);\n"); + WRITE(p, " float3 pos_u = tess_sample(_pos, weights);\n"); + + WRITE(p, " float3 du = pos_r - pos_l;\n"); + WRITE(p, " float3 dv = pos_d - pos_u;\n"); + } + WRITE(p, " float3 nrm = cross(du, dv);\n"); + WRITE(p, " nrm = normalize(nrm);\n"); + } + WRITE(p, " float3 worldpos = mul(float4(pos.xyz, 1.0), u_world);\n"); + if (hasNormal) + WRITE(p, " float3 worldnormal = normalize(mul(float4(%snrm, 0.0), u_world));\n", flipNormalTess ? "-" : ""); + else + WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n"); + } else { + WRITE(p, " float3 worldpos = mul(float4(In.position.xyz, 1.0), u_world);\n"); + if (hasNormal) + WRITE(p, " float3 worldnormal = normalize(mul(float4(%sIn.normal, 0.0), u_world));\n", flipNormal ? "-" : ""); + else + WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n"); } WRITE(p, " float4 viewPos = float4(mul(float4(worldpos, 1.0), u_view), 1.0);\n"); diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index a02fe9f3c4..7fc17ea5c1 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -15,52 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -// Ideas for speeding things up on mobile OpenGL ES implementations -// -// Use superbuffers! Yes I just invented that name. -// -// The idea is to avoid respecifying the vertex format between every draw call (multiple glVertexAttribPointer ...) -// by combining the contents of multiple draw calls into one buffer, as long as -// they have exactly the same output vertex format. (different input formats is fine! This way -// we can combine the data for multiple draws with different numbers of bones, as we consider numbones < 4 to be = 4) -// into one VBO. -// -// This will likely be a win because I believe that between every change of VBO + glVertexAttribPointer*N, the driver will -// perform a lot of validation, probably at draw call time, while all the validation can be skipped if the only thing -// that changes between two draw calls is simple state or texture or a matrix etc, not anything vertex related. -// Also the driver will have to manage hundreds instead of thousands of VBOs in games like GTA. -// -// * Every 10 frames or something, do the following: -// - Frame 1: -// + Mark all drawn buffers with in-frame sequence numbers (alternatively, -// just log them in an array) -// - Frame 2 (beginning?): -// + Take adjacent buffers that have the same output vertex format, and add them -// to a list of buffers to combine. Create said buffers with appropriate sizes -// and precompute the offsets that the draws should be written into. -// - Frame 2 (end): -// + Actually do the work of combining the buffers. This probably means re-decoding -// the vertices into a new one. Will also have to apply index offsets. -// -// Also need to change the drawing code so that we don't glBindBuffer and respecify glVAP if -// two subsequent drawcalls come from the same superbuffer. -// -// Or we ignore all of this including vertex caching and simply find a way to do highly optimized vertex streaming, -// like Dolphin is trying to. That will likely never be able to reach the same speed as perfectly optimized -// superbuffers though. For this we will have to JIT the vertex decoder but that's not too hard. -// -// Now, when do we delete superbuffers? Maybe when half the buffers within have been killed? -// -// Another idea for GTA which switches textures a lot while not changing much other state is to use ES 3 Array -// textures, if they are the same size (even if they aren't, might be okay to simply resize the textures to match -// if they're just a multiple of 2 away) or something. Then we'd have to add a W texture coordinate to choose the -// texture within the bound texture array to the vertex data when merging into superbuffers. -// -// There are even more things to try. For games that do matrix palette skinning by quickly switching bones and -// just drawing a few triangles per call (NBA, FF:CC, Tekken 6 etc) we could even collect matrices, upload them -// all at once, writing matrix indices into the vertices in addition to the weights, and then doing a single -// draw call with specially generated shader to draw the whole mesh. This code will be seriously complex though. - #include "base/logging.h" #include "base/timeutil.h" @@ -376,7 +330,7 @@ void DrawEngineGLES::DoFlush() { // Cannot cache vertex data with morph enabled. bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); - // Also avoid caching when software skinning. + // Also avoid caching when skinning. if (lastVType_ & GE_VTYPE_WEIGHT_MASK) useCache = false; @@ -522,7 +476,7 @@ void DrawEngineGLES::DoFlush() { vai->lastFrame = gpuStats.numFlips; } else { if (lastVType_ & GE_VTYPE_WEIGHT_MASK) { - // If software skinning, we've already predecoded into "decoded". So push that content. + // If skinning, we've already predecoded into "decoded". So push that content. size_t size = decodedVerts_ * dec_->GetDecVtxFmt().stride; u8 *dest = (u8 *)frameData.pushVertex->Push(size, &vertexBufferOffset, &vertexBuffer); memcpy(dest, decoded, size); diff --git a/GPU/GLES/VertexShaderGeneratorGLES.cpp b/GPU/GLES/VertexShaderGeneratorGLES.cpp index 239134b46b..d5357c72e4 100644 --- a/GPU/GLES/VertexShaderGeneratorGLES.cpp +++ b/GPU/GLES/VertexShaderGeneratorGLES.cpp @@ -436,114 +436,111 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, } } } else { - // Step 1: World Transform / Skinning - if (true) { - // Hardware tessellation - if (doBezier || doSpline) { - WRITE(p, " vec3 _pos[16];\n"); - WRITE(p, " vec2 _tex[16];\n"); - WRITE(p, " vec4 _col[16];\n"); - WRITE(p, " int num_patches_u = %s;\n", doBezier ? "(u_spline_count_u - 1) / 3" : "u_spline_count_u - 3"); - WRITE(p, " int u = int(mod(float(gl_InstanceID), float(num_patches_u)));\n"); - WRITE(p, " int v = gl_InstanceID / num_patches_u;\n"); - WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n"); - WRITE(p, " for (int i = 0; i < 4; i++) {\n"); - WRITE(p, " for (int j = 0; j < 4; j++) {\n"); - WRITE(p, " int index = (i + v%s) * u_spline_count_u + (j + u%s);\n", doBezier ? " * 3" : "", doBezier ? " * 3" : ""); - WRITE(p, " _pos[i * 4 + j] = %s(u_tess_pos_tex, ivec2(index, 0), 0).xyz;\n", texelFetch); - if (doTexture && hasTexcoord && hasTexcoordTess) - WRITE(p, " _tex[i * 4 + j] = %s(u_tess_tex_tex, ivec2(index, 0), 0).xy;\n", texelFetch); - if (hasColor && hasColorTess) - WRITE(p, " _col[i * 4 + j] = %s(u_tess_col_tex, ivec2(index, 0), 0).rgba;\n", texelFetch); - WRITE(p, " }\n"); - WRITE(p, " }\n"); - WRITE(p, " vec2 tess_pos = position.xy;\n"); - WRITE(p, " vec2 weights[4];\n"); - if (doBezier) { - // Bernstein 3D - WRITE(p, " weights[0] = (1.0 - tess_pos) * (1.0 - tess_pos) * (1.0 - tess_pos);\n"); - WRITE(p, " weights[1] = 3.0 * tess_pos * (1.0 - tess_pos) * (1.0 - tess_pos);\n"); - WRITE(p, " weights[2] = 3.0 * tess_pos * tess_pos * (1.0 - tess_pos);\n"); - WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n"); - } else { // Spline - WRITE(p, " ivec2 spline_num_patches = ivec2(u_spline_count_u - 3, u_spline_count_v - 3);\n"); - WRITE(p, " ivec2 spline_type = ivec2(u_spline_type_u, u_spline_type_v);\n"); - WRITE(p, " vec2 knots[6];\n"); - WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n"); - WRITE(p, " spline_weight(tess_pos + vec2(patch_pos), knots, weights);\n"); - } - WRITE(p, " vec3 pos = tess_sample(_pos, weights);\n"); - if (doTexture && hasTexcoord) { - if (hasTexcoordTess) - WRITE(p, " vec2 tex = tess_sample(_tex, weights);\n"); - else - WRITE(p, " vec2 tex = tess_pos + vec2(patch_pos);\n"); - } - if (hasColor) { - if (hasColorTess) - WRITE(p, " vec4 col = tess_sample(_col, weights);\n"); - else - WRITE(p, " vec4 col = %s(u_tess_col_tex, ivec2(0, 0), 0).rgba;\n", texelFetch); - } - if (hasNormal) { - // Curved surface is probably always need to compute normal(not sampling from control points) - if (doBezier) { - // Bernstein derivative - WRITE(p, " vec2 bernderiv[4];\n"); - WRITE(p, " bernderiv[0] = -3.0 * (tess_pos - 1.0) * (tess_pos - 1.0); \n"); - WRITE(p, " bernderiv[1] = 9.0 * tess_pos * tess_pos - 12.0 * tess_pos + 3.0; \n"); - WRITE(p, " bernderiv[2] = 3.0 * (2.0 - 3.0 * tess_pos) * tess_pos; \n"); - WRITE(p, " bernderiv[3] = 3.0 * tess_pos * tess_pos; \n"); - - WRITE(p, " vec2 bernderiv_u[4];\n"); - WRITE(p, " vec2 bernderiv_v[4];\n"); - WRITE(p, " for (int i = 0; i < 4; i++) {\n"); - WRITE(p, " bernderiv_u[i] = vec2(bernderiv[i].x, weights[i].y);\n"); - WRITE(p, " bernderiv_v[i] = vec2(weights[i].x, bernderiv[i].y);\n"); - WRITE(p, " }\n"); - - WRITE(p, " vec3 du = tess_sample(_pos, bernderiv_u);\n"); - WRITE(p, " vec3 dv = tess_sample(_pos, bernderiv_v);\n"); - } else { // Spline - WRITE(p, " vec2 tess_next_u = vec2(normal.x, 0.0);\n"); - WRITE(p, " vec2 tess_next_v = vec2(0.0, normal.y);\n"); - // Right - WRITE(p, " vec2 tess_pos_r = tess_pos + tess_next_u;\n"); - WRITE(p, " spline_weight(tess_pos_r + vec2(patch_pos), knots, weights);\n"); - WRITE(p, " vec3 pos_r = tess_sample(_pos, weights);\n"); - // Left - WRITE(p, " vec2 tess_pos_l = tess_pos - tess_next_u;\n"); - WRITE(p, " spline_weight(tess_pos_l + vec2(patch_pos), knots, weights);\n"); - WRITE(p, " vec3 pos_l = tess_sample(_pos, weights);\n"); - // Down - WRITE(p, " vec2 tess_pos_d = tess_pos + tess_next_v;\n"); - WRITE(p, " spline_weight(tess_pos_d + vec2(patch_pos), knots, weights);\n"); - WRITE(p, " vec3 pos_d = tess_sample(_pos, weights);\n"); - // Up - WRITE(p, " vec2 tess_pos_u = tess_pos - tess_next_v;\n"); - WRITE(p, " spline_weight(tess_pos_u + vec2(patch_pos), knots, weights);\n"); - WRITE(p, " vec3 pos_u = tess_sample(_pos, weights);\n"); - - WRITE(p, " vec3 du = pos_r - pos_l;\n"); - WRITE(p, " vec3 dv = pos_d - pos_u;\n"); - } - WRITE(p, " vec3 nrm = cross(du, dv);\n"); - WRITE(p, " nrm = normalize(nrm);\n"); - } - WRITE(p, " vec3 worldpos = (u_world * vec4(pos.xyz, 1.0)).xyz;\n"); - if (hasNormal) { - WRITE(p, " mediump vec3 worldnormal = normalize((u_world * vec4(%snrm, 0.0)).xyz);\n", flipNormalTess ? "-" : ""); - } else { - WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n"); - } - } else { - // No skinning, just standard T&L. - WRITE(p, " vec3 worldpos = (u_world * vec4(position.xyz, 1.0)).xyz;\n"); - if (hasNormal) - WRITE(p, " mediump vec3 worldnormal = normalize((u_world * vec4(%snormal, 0.0)).xyz);\n", flipNormal ? "-" : ""); - else - WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n"); + // Step 1: World Transform + // Hardware tessellation + if (doBezier || doSpline) { + WRITE(p, " vec3 _pos[16];\n"); + WRITE(p, " vec2 _tex[16];\n"); + WRITE(p, " vec4 _col[16];\n"); + WRITE(p, " int num_patches_u = %s;\n", doBezier ? "(u_spline_count_u - 1) / 3" : "u_spline_count_u - 3"); + WRITE(p, " int u = int(mod(float(gl_InstanceID), float(num_patches_u)));\n"); + WRITE(p, " int v = gl_InstanceID / num_patches_u;\n"); + WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n"); + WRITE(p, " for (int i = 0; i < 4; i++) {\n"); + WRITE(p, " for (int j = 0; j < 4; j++) {\n"); + WRITE(p, " int index = (i + v%s) * u_spline_count_u + (j + u%s);\n", doBezier ? " * 3" : "", doBezier ? " * 3" : ""); + WRITE(p, " _pos[i * 4 + j] = %s(u_tess_pos_tex, ivec2(index, 0), 0).xyz;\n", texelFetch); + if (doTexture && hasTexcoord && hasTexcoordTess) + WRITE(p, " _tex[i * 4 + j] = %s(u_tess_tex_tex, ivec2(index, 0), 0).xy;\n", texelFetch); + if (hasColor && hasColorTess) + WRITE(p, " _col[i * 4 + j] = %s(u_tess_col_tex, ivec2(index, 0), 0).rgba;\n", texelFetch); + WRITE(p, " }\n"); + WRITE(p, " }\n"); + WRITE(p, " vec2 tess_pos = position.xy;\n"); + WRITE(p, " vec2 weights[4];\n"); + if (doBezier) { + // Bernstein 3D + WRITE(p, " weights[0] = (1.0 - tess_pos) * (1.0 - tess_pos) * (1.0 - tess_pos);\n"); + WRITE(p, " weights[1] = 3.0 * tess_pos * (1.0 - tess_pos) * (1.0 - tess_pos);\n"); + WRITE(p, " weights[2] = 3.0 * tess_pos * tess_pos * (1.0 - tess_pos);\n"); + WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n"); + } else { // Spline + WRITE(p, " ivec2 spline_num_patches = ivec2(u_spline_count_u - 3, u_spline_count_v - 3);\n"); + WRITE(p, " ivec2 spline_type = ivec2(u_spline_type_u, u_spline_type_v);\n"); + WRITE(p, " vec2 knots[6];\n"); + WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n"); + WRITE(p, " spline_weight(tess_pos + vec2(patch_pos), knots, weights);\n"); } + WRITE(p, " vec3 pos = tess_sample(_pos, weights);\n"); + if (doTexture && hasTexcoord) { + if (hasTexcoordTess) + WRITE(p, " vec2 tex = tess_sample(_tex, weights);\n"); + else + WRITE(p, " vec2 tex = tess_pos + vec2(patch_pos);\n"); + } + if (hasColor) { + if (hasColorTess) + WRITE(p, " vec4 col = tess_sample(_col, weights);\n"); + else + WRITE(p, " vec4 col = %s(u_tess_col_tex, ivec2(0, 0), 0).rgba;\n", texelFetch); + } + if (hasNormal) { + // Curved surface is probably always need to compute normal(not sampling from control points) + if (doBezier) { + // Bernstein derivative + WRITE(p, " vec2 bernderiv[4];\n"); + WRITE(p, " bernderiv[0] = -3.0 * (tess_pos - 1.0) * (tess_pos - 1.0); \n"); + WRITE(p, " bernderiv[1] = 9.0 * tess_pos * tess_pos - 12.0 * tess_pos + 3.0; \n"); + WRITE(p, " bernderiv[2] = 3.0 * (2.0 - 3.0 * tess_pos) * tess_pos; \n"); + WRITE(p, " bernderiv[3] = 3.0 * tess_pos * tess_pos; \n"); + + WRITE(p, " vec2 bernderiv_u[4];\n"); + WRITE(p, " vec2 bernderiv_v[4];\n"); + WRITE(p, " for (int i = 0; i < 4; i++) {\n"); + WRITE(p, " bernderiv_u[i] = vec2(bernderiv[i].x, weights[i].y);\n"); + WRITE(p, " bernderiv_v[i] = vec2(weights[i].x, bernderiv[i].y);\n"); + WRITE(p, " }\n"); + + WRITE(p, " vec3 du = tess_sample(_pos, bernderiv_u);\n"); + WRITE(p, " vec3 dv = tess_sample(_pos, bernderiv_v);\n"); + } else { // Spline + WRITE(p, " vec2 tess_next_u = vec2(normal.x, 0.0);\n"); + WRITE(p, " vec2 tess_next_v = vec2(0.0, normal.y);\n"); + // Right + WRITE(p, " vec2 tess_pos_r = tess_pos + tess_next_u;\n"); + WRITE(p, " spline_weight(tess_pos_r + vec2(patch_pos), knots, weights);\n"); + WRITE(p, " vec3 pos_r = tess_sample(_pos, weights);\n"); + // Left + WRITE(p, " vec2 tess_pos_l = tess_pos - tess_next_u;\n"); + WRITE(p, " spline_weight(tess_pos_l + vec2(patch_pos), knots, weights);\n"); + WRITE(p, " vec3 pos_l = tess_sample(_pos, weights);\n"); + // Down + WRITE(p, " vec2 tess_pos_d = tess_pos + tess_next_v;\n"); + WRITE(p, " spline_weight(tess_pos_d + vec2(patch_pos), knots, weights);\n"); + WRITE(p, " vec3 pos_d = tess_sample(_pos, weights);\n"); + // Up + WRITE(p, " vec2 tess_pos_u = tess_pos - tess_next_v;\n"); + WRITE(p, " spline_weight(tess_pos_u + vec2(patch_pos), knots, weights);\n"); + WRITE(p, " vec3 pos_u = tess_sample(_pos, weights);\n"); + + WRITE(p, " vec3 du = pos_r - pos_l;\n"); + WRITE(p, " vec3 dv = pos_d - pos_u;\n"); + } + WRITE(p, " vec3 nrm = cross(du, dv);\n"); + WRITE(p, " nrm = normalize(nrm);\n"); + } + WRITE(p, " vec3 worldpos = (u_world * vec4(pos.xyz, 1.0)).xyz;\n"); + if (hasNormal) { + WRITE(p, " mediump vec3 worldnormal = normalize((u_world * vec4(%snrm, 0.0)).xyz);\n", flipNormalTess ? "-" : ""); + } else { + WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n"); + } + } else { + WRITE(p, " vec3 worldpos = (u_world * vec4(position.xyz, 1.0)).xyz;\n"); + if (hasNormal) + WRITE(p, " mediump vec3 worldnormal = normalize((u_world * vec4(%snormal, 0.0)).xyz);\n", flipNormal ? "-" : ""); + else + WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n"); } WRITE(p, " vec4 viewPos = u_view * vec4(worldpos, 1.0);\n"); diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index c3acc89267..6d6486dd29 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -578,7 +578,7 @@ void DrawEngineVulkan::DoFlush() { // Cannot cache vertex data with morph enabled. bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); - // Also avoid caching when software skinning. + // Also avoid caching when skinning. VkBuffer vbuf = VK_NULL_HANDLE; VkBuffer ibuf = VK_NULL_HANDLE; if (lastVType_ & GE_VTYPE_WEIGHT_MASK) { @@ -724,7 +724,7 @@ void DrawEngineVulkan::DoFlush() { } } else { if (lastVType_ & GE_VTYPE_WEIGHT_MASK) { - // If software skinning, we've already predecoded into "decoded". So push that content. + // If skinning, we've already predecoded into "decoded". So push that content. VkDeviceSize size = decodedVerts_ * dec_->GetDecVtxFmt().stride; u8 *dest = (u8 *)frame->pushVertex->Push(size, &vbOffset, &vbuf); memcpy(dest, decoded, size); diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp index a2e00e55d6..91b5175548 100644 --- a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp @@ -311,112 +311,109 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *use } } else { // Step 1: World Transform / Skinning - if (true) { - if (doBezier || doSpline) { - WRITE(p, " vec3 _pos[16];\n"); - WRITE(p, " vec2 _tex[16];\n"); - WRITE(p, " vec4 _col[16];\n"); - WRITE(p, " int num_patches_u = %s;\n", doBezier ? "(base.spline_count_u - 1) / 3" : "base.spline_count_u - 3"); - WRITE(p, " int u = int(mod(gl_InstanceIndex, num_patches_u));\n"); - WRITE(p, " int v = gl_InstanceIndex / num_patches_u;\n"); - WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n"); - WRITE(p, " for (int i = 0; i < 4; i++) {\n"); - WRITE(p, " for (int j = 0; j < 4; j++) {\n"); - WRITE(p, " int idx = (i + v%s) * base.spline_count_u + (j + u%s);\n", doBezier ? " * 3" : "", doBezier ? " * 3" : ""); - WRITE(p, " _pos[i * 4 + j] = tess_data.data[idx].pos.xyz;\n"); - if (doTexture && hasTexcoord && hasTexcoordTess) - WRITE(p, " _tex[i * 4 + j] = tess_data.data[idx].uv.xy;\n"); - if (hasColor && hasColorTess) - WRITE(p, " _col[i * 4 + j] = tess_data.data[idx].color;\n"); - WRITE(p, " }\n"); - WRITE(p, " }\n"); - WRITE(p, " vec2 tess_pos = position.xy;\n"); - WRITE(p, " vec2 weights[4];\n"); - if (doBezier) { - // Bernstein 3D - WRITE(p, " weights[0] = (1 - tess_pos) * (1 - tess_pos) * (1 - tess_pos);\n"); - WRITE(p, " weights[1] = 3 * tess_pos * (1 - tess_pos) * (1 - tess_pos);\n"); - WRITE(p, " weights[2] = 3 * tess_pos * tess_pos * (1 - tess_pos);\n"); - WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n"); - } else { // Spline - WRITE(p, " ivec2 spline_num_patches = ivec2(base.spline_count_u - 3, base.spline_count_v - 3);\n"); - WRITE(p, " ivec2 spline_type = ivec2(base.spline_type_u, base.spline_type_v);\n"); - WRITE(p, " vec2 knots[6];\n"); - WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n"); - WRITE(p, " spline_weight(tess_pos + patch_pos, knots, weights);\n"); - } - WRITE(p, " vec3 pos = tess_sample(_pos, weights);\n"); - if (doTexture && hasTexcoord) { - if (hasTexcoordTess) - WRITE(p, " vec2 tex = tess_sample(_tex, weights);\n"); - else - WRITE(p, " vec2 tex = tess_pos + patch_pos;\n"); - } - if (hasColor) { - if (hasColorTess) - WRITE(p, " vec4 col = tess_sample(_col, weights);\n"); - else - WRITE(p, " vec4 col = tess_data.data[0].color;\n"); - } - if (hasNormal) { - // Curved surface is probably always need to compute normal(not sampling from control points) - if (doBezier) { - // Bernstein derivative - WRITE(p, " vec2 bernderiv[4];\n"); - WRITE(p, " bernderiv[0] = -3 * (tess_pos - 1) * (tess_pos - 1); \n"); - WRITE(p, " bernderiv[1] = 9 * tess_pos * tess_pos - 12 * tess_pos + 3; \n"); - WRITE(p, " bernderiv[2] = 3 * (2 - 3 * tess_pos) * tess_pos; \n"); - WRITE(p, " bernderiv[3] = 3 * tess_pos * tess_pos; \n"); - - WRITE(p, " vec2 bernderiv_u[4];\n"); - WRITE(p, " vec2 bernderiv_v[4];\n"); - WRITE(p, " for (int i = 0; i < 4; i++) {\n"); - WRITE(p, " bernderiv_u[i] = vec2(bernderiv[i].x, weights[i].y);\n"); - WRITE(p, " bernderiv_v[i] = vec2(weights[i].x, bernderiv[i].y);\n"); - WRITE(p, " }\n"); - - WRITE(p, " vec3 du = tess_sample(_pos, bernderiv_u);\n"); - WRITE(p, " vec3 dv = tess_sample(_pos, bernderiv_v);\n"); - } else { // Spline - WRITE(p, " vec2 tess_next_u = vec2(normal.x, 0);\n"); - WRITE(p, " vec2 tess_next_v = vec2(0, normal.y);\n"); - // Right - WRITE(p, " vec2 tess_pos_r = tess_pos + tess_next_u;\n"); - WRITE(p, " spline_weight(tess_pos_r + patch_pos, knots, weights);\n"); - WRITE(p, " vec3 pos_r = tess_sample(_pos, weights);\n"); - // Left - WRITE(p, " vec2 tess_pos_l = tess_pos - tess_next_u;\n"); - WRITE(p, " spline_weight(tess_pos_l + patch_pos, knots, weights);\n"); - WRITE(p, " vec3 pos_l = tess_sample(_pos, weights);\n"); - // Down - WRITE(p, " vec2 tess_pos_d = tess_pos + tess_next_v;\n"); - WRITE(p, " spline_weight(tess_pos_d + patch_pos, knots, weights);\n"); - WRITE(p, " vec3 pos_d = tess_sample(_pos, weights);\n"); - // Up - WRITE(p, " vec2 tess_pos_u = tess_pos - tess_next_v;\n"); - WRITE(p, " spline_weight(tess_pos_u + patch_pos, knots, weights);\n"); - WRITE(p, " vec3 pos_u = tess_sample(_pos, weights);\n"); - - WRITE(p, " vec3 du = pos_r - pos_l;\n"); - WRITE(p, " vec3 dv = pos_d - pos_u;\n"); - } - WRITE(p, " vec3 nrm = cross(du, dv);\n"); - WRITE(p, " nrm = normalize(nrm);\n"); - } - WRITE(p, " vec3 worldpos = vec4(pos.xyz, 1.0) * base.world_mtx;\n"); - if (hasNormal) { - WRITE(p, " mediump vec3 worldnormal = normalize(vec4(%snrm, 0.0) * base.world_mtx);\n", flipNormalTess ? "-" : ""); - } else { - WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n"); - } - } else { - // No skinning, just standard T&L. - WRITE(p, " vec3 worldpos = vec4(position.xyz, 1.0) * base.world_mtx;\n"); - if (hasNormal) - WRITE(p, " mediump vec3 worldnormal = normalize(vec4(%snormal, 0.0) * base.world_mtx);\n", flipNormal ? "-" : ""); - else - WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n"); + if (doBezier || doSpline) { + WRITE(p, " vec3 _pos[16];\n"); + WRITE(p, " vec2 _tex[16];\n"); + WRITE(p, " vec4 _col[16];\n"); + WRITE(p, " int num_patches_u = %s;\n", doBezier ? "(base.spline_count_u - 1) / 3" : "base.spline_count_u - 3"); + WRITE(p, " int u = int(mod(gl_InstanceIndex, num_patches_u));\n"); + WRITE(p, " int v = gl_InstanceIndex / num_patches_u;\n"); + WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n"); + WRITE(p, " for (int i = 0; i < 4; i++) {\n"); + WRITE(p, " for (int j = 0; j < 4; j++) {\n"); + WRITE(p, " int idx = (i + v%s) * base.spline_count_u + (j + u%s);\n", doBezier ? " * 3" : "", doBezier ? " * 3" : ""); + WRITE(p, " _pos[i * 4 + j] = tess_data.data[idx].pos.xyz;\n"); + if (doTexture && hasTexcoord && hasTexcoordTess) + WRITE(p, " _tex[i * 4 + j] = tess_data.data[idx].uv.xy;\n"); + if (hasColor && hasColorTess) + WRITE(p, " _col[i * 4 + j] = tess_data.data[idx].color;\n"); + WRITE(p, " }\n"); + WRITE(p, " }\n"); + WRITE(p, " vec2 tess_pos = position.xy;\n"); + WRITE(p, " vec2 weights[4];\n"); + if (doBezier) { + // Bernstein 3D + WRITE(p, " weights[0] = (1 - tess_pos) * (1 - tess_pos) * (1 - tess_pos);\n"); + WRITE(p, " weights[1] = 3 * tess_pos * (1 - tess_pos) * (1 - tess_pos);\n"); + WRITE(p, " weights[2] = 3 * tess_pos * tess_pos * (1 - tess_pos);\n"); + WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n"); + } else { // Spline + WRITE(p, " ivec2 spline_num_patches = ivec2(base.spline_count_u - 3, base.spline_count_v - 3);\n"); + WRITE(p, " ivec2 spline_type = ivec2(base.spline_type_u, base.spline_type_v);\n"); + WRITE(p, " vec2 knots[6];\n"); + WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n"); + WRITE(p, " spline_weight(tess_pos + patch_pos, knots, weights);\n"); } + WRITE(p, " vec3 pos = tess_sample(_pos, weights);\n"); + if (doTexture && hasTexcoord) { + if (hasTexcoordTess) + WRITE(p, " vec2 tex = tess_sample(_tex, weights);\n"); + else + WRITE(p, " vec2 tex = tess_pos + patch_pos;\n"); + } + if (hasColor) { + if (hasColorTess) + WRITE(p, " vec4 col = tess_sample(_col, weights);\n"); + else + WRITE(p, " vec4 col = tess_data.data[0].color;\n"); + } + if (hasNormal) { + // Curved surface is probably always need to compute normal(not sampling from control points) + if (doBezier) { + // Bernstein derivative + WRITE(p, " vec2 bernderiv[4];\n"); + WRITE(p, " bernderiv[0] = -3 * (tess_pos - 1) * (tess_pos - 1); \n"); + WRITE(p, " bernderiv[1] = 9 * tess_pos * tess_pos - 12 * tess_pos + 3; \n"); + WRITE(p, " bernderiv[2] = 3 * (2 - 3 * tess_pos) * tess_pos; \n"); + WRITE(p, " bernderiv[3] = 3 * tess_pos * tess_pos; \n"); + + WRITE(p, " vec2 bernderiv_u[4];\n"); + WRITE(p, " vec2 bernderiv_v[4];\n"); + WRITE(p, " for (int i = 0; i < 4; i++) {\n"); + WRITE(p, " bernderiv_u[i] = vec2(bernderiv[i].x, weights[i].y);\n"); + WRITE(p, " bernderiv_v[i] = vec2(weights[i].x, bernderiv[i].y);\n"); + WRITE(p, " }\n"); + + WRITE(p, " vec3 du = tess_sample(_pos, bernderiv_u);\n"); + WRITE(p, " vec3 dv = tess_sample(_pos, bernderiv_v);\n"); + } else { // Spline + WRITE(p, " vec2 tess_next_u = vec2(normal.x, 0);\n"); + WRITE(p, " vec2 tess_next_v = vec2(0, normal.y);\n"); + // Right + WRITE(p, " vec2 tess_pos_r = tess_pos + tess_next_u;\n"); + WRITE(p, " spline_weight(tess_pos_r + patch_pos, knots, weights);\n"); + WRITE(p, " vec3 pos_r = tess_sample(_pos, weights);\n"); + // Left + WRITE(p, " vec2 tess_pos_l = tess_pos - tess_next_u;\n"); + WRITE(p, " spline_weight(tess_pos_l + patch_pos, knots, weights);\n"); + WRITE(p, " vec3 pos_l = tess_sample(_pos, weights);\n"); + // Down + WRITE(p, " vec2 tess_pos_d = tess_pos + tess_next_v;\n"); + WRITE(p, " spline_weight(tess_pos_d + patch_pos, knots, weights);\n"); + WRITE(p, " vec3 pos_d = tess_sample(_pos, weights);\n"); + // Up + WRITE(p, " vec2 tess_pos_u = tess_pos - tess_next_v;\n"); + WRITE(p, " spline_weight(tess_pos_u + patch_pos, knots, weights);\n"); + WRITE(p, " vec3 pos_u = tess_sample(_pos, weights);\n"); + + WRITE(p, " vec3 du = pos_r - pos_l;\n"); + WRITE(p, " vec3 dv = pos_d - pos_u;\n"); + } + WRITE(p, " vec3 nrm = cross(du, dv);\n"); + WRITE(p, " nrm = normalize(nrm);\n"); + } + WRITE(p, " vec3 worldpos = vec4(pos.xyz, 1.0) * base.world_mtx;\n"); + if (hasNormal) { + WRITE(p, " mediump vec3 worldnormal = normalize(vec4(%snrm, 0.0) * base.world_mtx);\n", flipNormalTess ? "-" : ""); + } else { + WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n"); + } + } else { + WRITE(p, " vec3 worldpos = vec4(position.xyz, 1.0) * base.world_mtx;\n"); + if (hasNormal) + WRITE(p, " mediump vec3 worldnormal = normalize(vec4(%snormal, 0.0) * base.world_mtx);\n", flipNormal ? "-" : ""); + else + WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n"); } WRITE(p, " vec4 viewPos = vec4(vec4(worldpos, 1.0) * base.view_mtx, 1.0);\n"); From f086a0915f03c32035a37bc82d2217999760ebf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 2 Mar 2018 16:30:07 +0100 Subject: [PATCH 229/291] Further cleanup after the removal of hardware skinning. --- GPU/Common/ShaderId.cpp | 1 - GPU/Common/ShaderId.h | 3 +-- GPU/D3D11/ShaderManagerD3D11.h | 7 ------- GPU/Directx9/VertexShaderGeneratorDX9.cpp | 3 --- GPU/Directx9/VertexShaderGeneratorDX9.h | 2 -- 5 files changed, 1 insertion(+), 15 deletions(-) diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index 8a1667f181..7fcc34fd14 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -45,7 +45,6 @@ std::string VertexShaderDesc(const ShaderID &id) { } } if (id.Bits(VS_BIT_MATERIAL_UPDATE, 3)) desc << "MatUp:" << id.Bits(VS_BIT_MATERIAL_UPDATE, 3) << " "; - if (id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2)) desc << "WScale " << id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2) << " "; if (id.Bit(VS_BIT_FLATSHADE)) desc << "Flat "; if (id.Bit(VS_BIT_BEZIER)) desc << "Bezier "; diff --git a/GPU/Common/ShaderId.h b/GPU/Common/ShaderId.h index 8ef501a571..7606010b7e 100644 --- a/GPU/Common/ShaderId.h +++ b/GPU/Common/ShaderId.h @@ -44,8 +44,7 @@ enum { VS_BIT_LIGHT2_ENABLE = 54, VS_BIT_LIGHT3_ENABLE = 55, VS_BIT_LIGHTING_ENABLE = 56, - VS_BIT_WEIGHT_FMTSCALE = 57, // only two bits - // 59 - 61 are free. + // 57 - 61 are free. VS_BIT_FLATSHADE = 62, // 1 bit VS_BIT_BEZIER = 63, // 1 bit // No more free diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index 1ca3db44bb..3b4a21b961 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -105,13 +105,6 @@ public: // Applies dirty changes and copies the buffer. bool IsBaseDirty() { return true; } bool IsLightDirty() { return true; } - bool IsBoneDirty() { return true; } - - /* - uint32_t PushBaseBuffer(D3D11PushBuffer *dest, VkBuffer *buf); - uint32_t PushLightBuffer(D3D11PushBuffer *dest, VkBuffer *buf); - uint32_t PushBoneBuffer(D3D11PushBuffer *dest, VkBuffer *buf); - */ private: void Clear(); diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.cpp b/GPU/Directx9/VertexShaderGeneratorDX9.cpp index b3d35fc478..0863a9bf66 100644 --- a/GPU/Directx9/VertexShaderGeneratorDX9.cpp +++ b/GPU/Directx9/VertexShaderGeneratorDX9.cpp @@ -89,9 +89,6 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage } } - int numBoneWeights = 0; - int boneWeightScale = id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2); - if (lang == HLSL_DX9) { WRITE(p, "#pragma warning( disable : 3571 )\n"); if (isModeThrough) { diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.h b/GPU/Directx9/VertexShaderGeneratorDX9.h index 585fec012a..062e4a1dcb 100644 --- a/GPU/Directx9/VertexShaderGeneratorDX9.h +++ b/GPU/Directx9/VertexShaderGeneratorDX9.h @@ -21,8 +21,6 @@ namespace DX9 { -// #define USE_BONE_ARRAY - void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage lang = HLSL_DX9); enum { From 8ff5704fbf4eb6c8e756ec20c84b6848218aaaf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 5 Mar 2018 00:03:03 +0100 Subject: [PATCH 230/291] Fix indentation mistake, minor cleanup. --- GPU/Directx9/VertexShaderGeneratorDX9.cpp | 2 +- GPU/GPUState.h | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.cpp b/GPU/Directx9/VertexShaderGeneratorDX9.cpp index 0863a9bf66..4c2b5df7f1 100644 --- a/GPU/Directx9/VertexShaderGeneratorDX9.cpp +++ b/GPU/Directx9/VertexShaderGeneratorDX9.cpp @@ -37,7 +37,7 @@ namespace DX9 { - enum DoLightComputation { +enum DoLightComputation { LIGHT_OFF, LIGHT_SHADE, LIGHT_FULL, diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 18d43d0691..8e6a7c8665 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -441,10 +441,6 @@ struct GPUgstate { void Restore(u32_le *ptr); }; -inline int vertTypeGetNumBoneWeights(u32 vertType) { return 1 + ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); } -inline int vertTypeGetWeightMask(u32 vertType) { return vertType & GE_VTYPE_WEIGHT_MASK; } -inline int vertTypeGetTexCoordMask(u32 vertType) { return vertType & GE_VTYPE_TC_MASK; } - // The rest is cached simplified/converted data for fast access. // Does not need to be saved when saving/restoring context. // From 87575910df4ca68299b3391526885317fe13fd3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 5 Mar 2018 00:43:54 +0100 Subject: [PATCH 231/291] Oops, fix hardware tess in Vulkan (after removing hw skinning, we need to adjust the binding number) --- GPU/Vulkan/VertexShaderGeneratorVulkan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp index 91b5175548..e4aa9e729c 100644 --- a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp @@ -203,7 +203,7 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *use WRITE(p, " vec4 uv;\n"); WRITE(p, " vec4 color;\n"); WRITE(p, "};"); - WRITE(p, "layout (std430, set = 0, binding = 5) buffer s_tess_data {\n"); + WRITE(p, "layout (std430, set = 0, binding = 4) buffer s_tess_data {\n"); WRITE(p, " TessData data[];"); WRITE(p, "} tess_data;"); From 4cf5999bc81b65386c75cca503e56f9831a2c5eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 5 Mar 2018 12:24:02 +0100 Subject: [PATCH 232/291] Move the vertTypeID calculation out of DrawEngine. Need to shorten SubmitPrim as much as possible. --- GPU/Common/DrawEngineCommon.cpp | 33 +++++++++++++++------------------ GPU/Common/DrawEngineCommon.h | 15 +++++++++++---- GPU/Common/SplineCommon.cpp | 7 +++++-- GPU/GPUCommon.cpp | 8 +++++--- GPU/Null/NullGpu.cpp | 2 +- GPU/Software/TransformUnit.cpp | 4 ++-- 6 files changed, 39 insertions(+), 30 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 472056893d..663c782dfd 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -93,7 +93,7 @@ int DrawEngineCommon::ComputeNumVertsToDecode() const { void DrawEngineCommon::DecodeVerts(u8 *dest) { const UVScale origUV = gstate_c.uv; for (; decodeCounter_ < numDrawCalls; decodeCounter_++) { - gstate_c.uv = uvScale[decodeCounter_]; + gstate_c.uv = drawCalls[decodeCounter_].uvScale; DecodeVertsStep(dest, decodeCounter_, decodedVerts_); // NOTE! DecodeVertsStep can modify decodeCounter_! } gstate_c.uv = origUV; @@ -601,11 +601,12 @@ ReliableHashType DrawEngineCommon::ComputeHash() { } } - fullhash += DoReliableHash(&uvScale[0], sizeof(uvScale[0]) * numDrawCalls, 0x0123e658); + fullhash += DoReliableHash(&drawCalls[0].uvScale, sizeof(drawCalls[0].uvScale) * numDrawCalls, 0x0123e658); return fullhash; } -void DrawEngineCommon::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) { +// vertTypeID is the vertex type but with the UVGen mode smashed into the top bits. +void DrawEngineCommon::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int *bytesRead) { if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawCalls >= MAX_DEFERRED_DRAW_CALLS || vertexCountInDrawCalls_ + vertexCount > VERTEX_BUFFER_MAX) { DispatchFlush(); } @@ -617,9 +618,6 @@ void DrawEngineCommon::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, prevPrim_ = prim; } - // As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it - // into the top of the verttype where there are unused bits. - const u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24); // If vtype has changed, setup the vertex decoder. if (vertTypeID != lastVType_) { dec_ = GetVertexDecoder(vertTypeID); @@ -630,35 +628,34 @@ void DrawEngineCommon::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, if ((vertexCount < 2 && prim > 0) || (vertexCount < 3 && prim > 2 && prim != GE_PRIM_RECTANGLES)) return; - DeferredDrawCall &dc = drawCalls[numDrawCalls]; - dc.verts = verts; - dc.inds = inds; - dc.indexType = (vertType & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT; - dc.prim = prim; - dc.vertexCount = vertexCount; - if (g_Config.bVertexCache) { u32 dhash = dcid_; dhash = __rotl(dhash ^ (u32)(uintptr_t)verts, 13); dhash = __rotl(dhash ^ (u32)(uintptr_t)inds, 13); - dhash = __rotl(dhash ^ (u32)vertType, 13); + dhash = __rotl(dhash ^ (u32)vertTypeID, 13); dhash = __rotl(dhash ^ (u32)vertexCount, 13); dcid_ = dhash ^ (u32)prim; } + DeferredDrawCall &dc = drawCalls[numDrawCalls]; + dc.verts = verts; + dc.inds = inds; + dc.indexType = (vertTypeID & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT; + dc.prim = prim; + dc.vertexCount = vertexCount; + dc.uvScale = gstate_c.uv; + if (inds) { - GetIndexBounds(inds, vertexCount, vertType, &dc.indexLowerBound, &dc.indexUpperBound); + GetIndexBounds(inds, vertexCount, vertTypeID, &dc.indexLowerBound, &dc.indexUpperBound); } else { dc.indexLowerBound = 0; dc.indexUpperBound = vertexCount - 1; } - uvScale[numDrawCalls] = gstate_c.uv; - numDrawCalls++; vertexCountInDrawCalls_ += vertexCount; - if (vertType & GE_VTYPE_WEIGHT_MASK) { + if (vertTypeID & GE_VTYPE_WEIGHT_MASK) { DecodeVertsStep(decoded, decodeCounter_, decodedVerts_); decodeCounter_++; } diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 0bf9a30525..ae6854a586 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -44,6 +44,12 @@ typedef u64 ReliableHashType; typedef u32 ReliableHashType; #endif +inline uint32_t GetVertTypeID(uint32_t vertType, int uvGenMode) { + // As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it + // into the top of the verttype where there are unused bits. + return (vertType & 0xFFFFFF) | (uvGenMode << 24); +} + class DrawEngineCommon { public: DrawEngineCommon(); @@ -59,13 +65,14 @@ public: // This would seem to be unnecessary now, but is still required for splines/beziers to work in the software backend since SubmitPrim // is different. Should probably refactor that. - virtual void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) { - SubmitPrim(verts, inds, prim, vertexCount, vertType, bytesRead); + // Note that vertTypeID should be computed using GetVertTypeID(). + virtual void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int *bytesRead) { + SubmitPrim(verts, inds, prim, vertexCount, vertTypeID, bytesRead); } bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType, int *bytesRead); - void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead); + void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int *bytesRead); void SubmitSpline(const void *control_points, const void *indices, int tess_u, int tess_v, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, bool computeNormals, bool patchFacing, u32 vertType, int *bytesRead); void SubmitBezier(const void *control_points, const void *indices, int tess_u, int tess_v, int count_u, int count_v, GEPatchPrimType prim_type, bool computeNormals, bool patchFacing, u32 vertType, int *bytesRead); @@ -135,13 +142,13 @@ protected: u32 vertexCount; u16 indexLowerBound; u16 indexUpperBound; + UVScale uvScale; }; enum { MAX_DEFERRED_DRAW_CALLS = 128 }; DeferredDrawCall drawCalls[MAX_DEFERRED_DRAW_CALLS]; int numDrawCalls = 0; int vertexCountInDrawCalls_ = 0; - UVScale uvScale[MAX_DEFERRED_DRAW_CALLS]; int decimationCounter_ = 0; int decodeCounter_ = 0; diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index 8e428b695e..41eb4aec93 100644 --- a/GPU/Common/SplineCommon.cpp +++ b/GPU/Common/SplineCommon.cpp @@ -949,8 +949,10 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi gstate_c.uv.vOff = 0.0f; } + uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode()); + int generatedBytesRead; - DispatchSubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeWithIndex16, &generatedBytesRead); + DispatchSubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeID, &generatedBytesRead); DispatchFlush(); @@ -1091,8 +1093,9 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi gstate_c.uv.vOff = 0; } + uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode()); int generatedBytesRead; - DispatchSubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeWithIndex16, &generatedBytesRead); + DispatchSubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeID, &generatedBytesRead); DispatchFlush(); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index d128baa857..3101373da0 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1498,7 +1498,8 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { int bytesRead = 0; UpdateUVScaleOffset(); - drawEngineCommon_->SubmitPrim(verts, inds, prim, count, vertexType, &bytesRead); + uint32_t vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode()); + drawEngineCommon_->SubmitPrim(verts, inds, prim, count, vertTypeID, &bytesRead); // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). // Some games rely on this, they don't bother reloading VADDR and IADDR. // The VADDR/IADDR registers are NOT updated. @@ -1543,7 +1544,7 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { inds = Memory::GetPointerUnchecked(indexAddr); } - drawEngineCommon_->SubmitPrim(verts, inds, newPrim, count, vertexType, &bytesRead); + drawEngineCommon_->SubmitPrim(verts, inds, newPrim, count, vertTypeID, &bytesRead); AdvanceVerts(vertexType, count, bytesRead); totalVertCount += count; break; @@ -2047,7 +2048,8 @@ void GPUCommon::FlushImm() { int vtype = GE_VTYPE_POS_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_THROUGH; int bytesRead; - drawEngineCommon_->DispatchSubmitPrim(temp, nullptr, immPrim_, immCount_, vtype, &bytesRead); + uint32_t vertTypeID = GetVertTypeID(vtype, 0); + drawEngineCommon_->DispatchSubmitPrim(temp, nullptr, immPrim_, immCount_, vertTypeID, &bytesRead); drawEngineCommon_->DispatchFlush(); // TOOD: In the future, make a special path for these. // drawEngineCommon_->DispatchSubmitImm(immBuffer_, immCount_); diff --git a/GPU/Null/NullGpu.cpp b/GPU/Null/NullGpu.cpp index 2772718ec9..a240840496 100644 --- a/GPU/Null/NullGpu.cpp +++ b/GPU/Null/NullGpu.cpp @@ -29,7 +29,7 @@ class NullDrawEngine : public DrawEngineCommon { public: void DispatchFlush() override { } - void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) override { + void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int *bytesRead) override { } }; diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 8a3bd02232..e6bc3fbba0 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -53,8 +53,8 @@ SoftwareDrawEngine::~SoftwareDrawEngine() { void SoftwareDrawEngine::DispatchFlush() { } -void SoftwareDrawEngine::DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) { - transformUnit.SubmitPrimitive(verts, inds, prim, vertexCount, vertType, bytesRead, this); +void SoftwareDrawEngine::DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int *bytesRead) { + transformUnit.SubmitPrimitive(verts, inds, prim, vertexCount, vertTypeID, bytesRead, this); } VertexDecoder *SoftwareDrawEngine::FindVertexDecoder(u32 vtype) { From 50de13d3d7f91422fa1a9d70725fdf4a51a12ac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 5 Mar 2018 12:49:55 +0100 Subject: [PATCH 233/291] Optimize the "inner interpreter" for God of War character drawing. Speeds the games up by 4% or so. (measured on the title screen though..) --- GPU/GPUCommon.cpp | 49 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 3101373da0..b14d11ae01 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1528,6 +1528,7 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { { u32 count = data & 0xFFFF; if (count == 0) { + // Ignore. break; } @@ -1536,12 +1537,7 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); inds = 0; if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { - u32 indexAddr = gstate_c.indexAddr; - if (!Memory::IsValidAddress(indexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad index address %08x!", indexAddr); - return; - } - inds = Memory::GetPointerUnchecked(indexAddr); + inds = Memory::GetPointerUnchecked(gstate_c.indexAddr); } drawEngineCommon_->SubmitPrim(verts, inds, newPrim, count, vertTypeID, &bytesRead); @@ -1550,20 +1546,56 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { break; } case GE_CMD_VERTEXTYPE: - // Some games spam redundant GE_CMD_VERTEXTYPE - if (data != vertexType) { // don't mask data, vertexType is unmasked + { + uint32_t diff = data ^ vertexType; + // don't mask upper bits, vertexType is unmasked + if (diff & ~GE_VTYPE_WEIGHTCOUNT_MASK) { goto bail; + } else { + vertexType = data; + vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode()); } break; + } case GE_CMD_VADDR: gstate_c.vertexAddr = gstate_c.getRelativeAddress(data & 0x00FFFFFF); break; + case GE_CMD_OFFSETADDR: + gstate.cmdmem[GE_CMD_OFFSETADDR] = data; + gstate_c.offsetAddr = data << 8; + break; case GE_CMD_BASE: gstate.cmdmem[GE_CMD_BASE] = data; break; case GE_CMD_NOP: case GE_CMD_NOP_FF: break; + case GE_CMD_BONEMATRIXNUMBER: + gstate.cmdmem[GE_CMD_BONEMATRIXNUMBER] = data; + break; + case GE_CMD_TEXSCALEU: + gstate.cmdmem[GE_CMD_TEXSCALEU] = data; + gstate_c.uv.uScale = getFloat24(data); + break; + case GE_CMD_TEXSCALEV: + gstate.cmdmem[GE_CMD_TEXSCALEV] = data; + gstate_c.uv.vScale = getFloat24(data); + break; + case GE_CMD_CALL: + { + // A bone matrix probably. If not we bail. + const u32 target = gstate_c.getRelativeAddress(data & 0x00FFFFFC); + if ((Memory::ReadUnchecked_U32(target) >> 24) == GE_CMD_BONEMATRIXDATA && + (Memory::ReadUnchecked_U32(target + 11 * 4) >> 24) == GE_CMD_BONEMATRIXDATA && + (Memory::ReadUnchecked_U32(target + 12 * 4) >> 24) == GE_CMD_RET && + (target > currentList->stall || target + 12 * 4 < currentList->stall)) { + FastLoadBoneMatrix(target); + } else { + goto bail; + } + break; + } + default: // All other commands might need a flush or something, stop this inner loop. goto bail; @@ -1573,6 +1605,7 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { } bail: + gstate.cmdmem[GE_CMD_VERTEXTYPE] = vertexType; // Skip over the commands we just read out manually. if (cmdCount > 0) { UpdatePC(currentList->pc, currentList->pc + cmdCount * 4); From 91b565ae20a62574378053259528c2531df7cb70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 5 Mar 2018 13:19:36 +0100 Subject: [PATCH 234/291] Minor simplification in X86/X64 vertex decoder jit --- GPU/Common/VertexDecoderX86.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/GPU/Common/VertexDecoderX86.cpp b/GPU/Common/VertexDecoderX86.cpp index 388be1e2d7..f1cf7a2b42 100644 --- a/GPU/Common/VertexDecoderX86.cpp +++ b/GPU/Common/VertexDecoderX86.cpp @@ -39,6 +39,13 @@ alignas(16) static const float by32768[4] = { 1.0f / 32768.0f, 1.0f / 32768.0f, 1.0f / 32768.0f, 1.0f / 32768.0f, }; +alignas(16) static const float by128_11[4] = { + 1.0f / 128.0f, 1.0f / 128.0f, 1.0f, 1.0f, +}; +alignas(16) static const float by32768_11[4] = { + 1.0f / 32768.0f, 1.0f / 32768.0f, 1.0f, 1.0f, +}; + alignas(16) static const u32 threeMasks[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0 }; alignas(16) static const u32 aOne[4] = {0, 0, 0, 0x3F800000}; @@ -222,20 +229,14 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int // Keep the scale/offset in a few fp registers if we need it. if (prescaleStep) { MOV(PTRBITS, R(tempReg1), ImmPtr(&gstate_c.uv)); - MOVSS(fpScaleOffsetReg, MDisp(tempReg1, 0)); - MOVSS(fpScratchReg, MDisp(tempReg1, 4)); - UNPCKLPS(fpScaleOffsetReg, R(fpScratchReg)); + MOVAPS(fpScaleOffsetReg, MatR(tempReg1)); if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_8BIT) { - MOV(PTRBITS, R(tempReg2), ImmPtr(&by128)); + MOV(PTRBITS, R(tempReg2), ImmPtr(&by128_11)); MULPS(fpScaleOffsetReg, MatR(tempReg2)); } else if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_16BIT) { - MOV(PTRBITS, R(tempReg2), ImmPtr(&by32768)); + MOV(PTRBITS, R(tempReg2), ImmPtr(&by32768_11)); MULPS(fpScaleOffsetReg, MatR(tempReg2)); } - MOVSS(fpScratchReg, MDisp(tempReg1, 8)); - MOVSS(fpScratchReg2, MDisp(tempReg1, 12)); - UNPCKLPS(fpScratchReg, R(fpScratchReg2)); - UNPCKLPD(fpScaleOffsetReg, R(fpScratchReg)); } // Let's not bother with a proper stack frame. We just grab the arguments and go. From b6cbbceac9e99eac5e137595a5da33399d09d6c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 5 Mar 2018 16:23:07 +0100 Subject: [PATCH 235/291] MOVUPS to be safe. --- GPU/Common/VertexDecoderX86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Common/VertexDecoderX86.cpp b/GPU/Common/VertexDecoderX86.cpp index f1cf7a2b42..f18d24a93d 100644 --- a/GPU/Common/VertexDecoderX86.cpp +++ b/GPU/Common/VertexDecoderX86.cpp @@ -229,7 +229,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int // Keep the scale/offset in a few fp registers if we need it. if (prescaleStep) { MOV(PTRBITS, R(tempReg1), ImmPtr(&gstate_c.uv)); - MOVAPS(fpScaleOffsetReg, MatR(tempReg1)); + MOVUPS(fpScaleOffsetReg, MatR(tempReg1)); if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_8BIT) { MOV(PTRBITS, R(tempReg2), ImmPtr(&by128_11)); MULPS(fpScaleOffsetReg, MatR(tempReg2)); From 0ed3deabe6b4723e918a9d2d36ad6407ccd017f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Mar 2018 16:34:27 +0100 Subject: [PATCH 236/291] Fix #10692 (crash when starting games from command line). Throw in some minor Vulkan fixes as well. --- GPU/Vulkan/DrawEngineVulkan.cpp | 8 ++++---- UI/EmuScreen.cpp | 2 +- ext/native/thin3d/VulkanQueueRunner.h | 2 +- ext/native/thin3d/VulkanRenderManager.h | 2 ++ 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 6d6486dd29..9cb39484de 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -809,9 +809,9 @@ void DrawEngineVulkan::DoFlush() { if (!ibuf) ibOffset = (uint32_t)frame->pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), &ibuf); int numInstances = tess ? numPatches : 1; - renderManager->DrawIndexed(pipelineLayout_, ds, 3, dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, numInstances, VK_INDEX_TYPE_UINT16); + renderManager->DrawIndexed(pipelineLayout_, ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, numInstances, VK_INDEX_TYPE_UINT16); } else { - renderManager->Draw(pipelineLayout_, ds, 3, dynamicUBOOffsets, vbuf, vbOffset, vertexCount); + renderManager->Draw(pipelineLayout_, ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, vertexCount); } } } else { @@ -913,12 +913,12 @@ void DrawEngineVulkan::DoFlush() { vbOffset = (uint32_t)frame->pushVertex->Push(drawBuffer, maxIndex * sizeof(TransformedVertex), &vbuf); ibOffset = (uint32_t)frame->pushIndex->Push(inds, sizeof(short) * numTrans, &ibuf); VkDeviceSize offsets[1] = { vbOffset }; - renderManager->DrawIndexed(pipelineLayout_, ds, 3, dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, numTrans, 1, VK_INDEX_TYPE_UINT16); + renderManager->DrawIndexed(pipelineLayout_, ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, numTrans, 1, VK_INDEX_TYPE_UINT16); } else { VkBuffer vbuf; vbOffset = (uint32_t)frame->pushVertex->Push(drawBuffer, numTrans * sizeof(TransformedVertex), &vbuf); VkDeviceSize offsets[1] = { vbOffset }; - renderManager->Draw(pipelineLayout_, ds, 3, dynamicUBOOffsets, vbuf, vbOffset, numTrans); + renderManager->Draw(pipelineLayout_, ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, numTrans); } } else if (result.action == SW_CLEAR) { // Note: we won't get here if the clear is alpha but not color, or color but not alpha. diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index ab663a202b..05fbd0986d 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1189,7 +1189,7 @@ void EmuScreen::renderUI() { DrawContext *thin3d = screenManager()->getDrawContext(); UIContext *ctx = screenManager()->getUIContext(); - + ctx->BeginFrame(); // This sets up some important states but not the viewport. ctx->Begin(); diff --git a/ext/native/thin3d/VulkanQueueRunner.h b/ext/native/thin3d/VulkanQueueRunner.h index 807d1e47e8..8257fa450a 100644 --- a/ext/native/thin3d/VulkanQueueRunner.h +++ b/ext/native/thin3d/VulkanQueueRunner.h @@ -32,7 +32,7 @@ struct VkRenderData { VkPipelineLayout pipelineLayout; VkDescriptorSet ds; int numUboOffsets; - uint32_t uboOffsets[3]; + uint32_t uboOffsets[2]; VkBuffer vbuffer; VkDeviceSize voffset; uint32_t count; diff --git a/ext/native/thin3d/VulkanRenderManager.h b/ext/native/thin3d/VulkanRenderManager.h index 19e5cc8cd0..87de896d4f 100644 --- a/ext/native/thin3d/VulkanRenderManager.h +++ b/ext/native/thin3d/VulkanRenderManager.h @@ -167,6 +167,7 @@ public: data.draw.vbuffer = vbuffer; data.draw.voffset = voffset; data.draw.numUboOffsets = numUboOffsets; + assert(numUboOffsets <= ARRAY_SIZE(data.drawIndexed.uboOffsets)); for (int i = 0; i < numUboOffsets; i++) data.draw.uboOffsets[i] = uboOffsets[i]; curRenderStep_->commands.push_back(data); @@ -185,6 +186,7 @@ public: data.drawIndexed.ibuffer = ibuffer; data.drawIndexed.ioffset = ioffset; data.drawIndexed.numUboOffsets = numUboOffsets; + assert(numUboOffsets <= ARRAY_SIZE(data.drawIndexed.uboOffsets)); for (int i = 0; i < numUboOffsets; i++) data.drawIndexed.uboOffsets[i] = uboOffsets[i]; data.drawIndexed.indexType = indexType; From 9f9903c02ea7d57ca39a8b37a10a0f3d6153329a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 11 Mar 2018 17:14:11 +0100 Subject: [PATCH 237/291] Fixes to vulkan restart logic on Android. Should help #10696 --- Common/Vulkan/VulkanContext.cpp | 9 ++++++--- Common/Vulkan/VulkanContext.h | 2 +- android/jni/AndroidVulkanContext.cpp | 14 ++++++++------ android/jni/AndroidVulkanContext.h | 2 ++ android/jni/app-android.cpp | 7 +++---- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index 12993524ef..5a232f2fa9 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -922,13 +922,16 @@ VkFence VulkanContext::CreateFence(bool presignalled) { return fence; } -void VulkanContext::DestroyDevice() { - ILOG("VulkanContext::DestroyDevice (performing deletes)"); - // If there happen to be any pending deletes, now is a good time. +void VulkanContext::PerformPendingDeletes() { for (int i = 0; i < ARRAY_SIZE(frame_); i++) { frame_[i].deleteList.PerformDeletes(device_); } Delete().PerformDeletes(device_); +} + +void VulkanContext::DestroyDevice() { + ILOG("VulkanContext::DestroyDevice (performing deletes)"); + PerformPendingDeletes(); vkDestroyDevice(device_, nullptr); device_ = nullptr; diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index 6b441d1ffa..6e03b92caf 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -148,9 +148,9 @@ public: // Also destroys the surface. void DestroyObjects(); - void DestroyDevice(); + void PerformPendingDeletes(); void WaitUntilQueueIdle(); // Utility functions for shorter code diff --git a/android/jni/AndroidVulkanContext.cpp b/android/jni/AndroidVulkanContext.cpp index e5f4987920..d41c6af5ad 100644 --- a/android/jni/AndroidVulkanContext.cpp +++ b/android/jni/AndroidVulkanContext.cpp @@ -169,22 +169,24 @@ bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredB return success; } -void AndroidVulkanContext::Shutdown() { +void AndroidVulkanContext::ShutdownFromRenderThread() { ILOG("AndroidVulkanContext::Shutdown"); draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); - ILOG("Calling NativeShutdownGraphics"); - NativeShutdownGraphics(); delete draw_; draw_ = nullptr; g_Vulkan->WaitUntilQueueIdle(); - g_Vulkan->DestroyObjects(); + g_Vulkan->PerformPendingDeletes(); + g_Vulkan->DestroyObjects(); // Also destroys the surface, a bit asymmetric + ILOG("Done with ShutdownFromRenderThread"); +} + +void AndroidVulkanContext::Shutdown() { + ILOG("Calling NativeShutdownGraphics"); g_Vulkan->DestroyDevice(); g_Vulkan->DestroyDebugMsgCallback(); g_Vulkan->DestroyInstance(); - // We keep the g_Vulkan context around to avoid invalidating a ton of pointers around the app. - finalize_glslang(); ILOG("AndroidVulkanContext::Shutdown completed"); } diff --git a/android/jni/AndroidVulkanContext.h b/android/jni/AndroidVulkanContext.h index affc330157..adb47e2806 100644 --- a/android/jni/AndroidVulkanContext.h +++ b/android/jni/AndroidVulkanContext.h @@ -14,6 +14,8 @@ public: bool InitAPI(); bool InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) override; + void ShutdownFromRenderThread() override; // Inverses InitFromRenderThread. + void Shutdown() override; void SwapInterval(int interval) override; void SwapBuffers() override; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index ad91edae81..49d472ceba 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -983,10 +983,9 @@ retry: NativeShutdownGraphics(); renderer_inited = false; - ILOG("Shutting down graphics context."); - graphicsContext->Shutdown(); - delete graphicsContext; - graphicsContext = nullptr; + // Shut the graphics context down to the same state it was in when we entered the render thread. + ILOG("Shutting down graphics context from render thread..."); + graphicsContext->ShutdownFromRenderThread(); renderLoopRunning = false; WLOG("Render loop function exited."); return true; From c1e05ae861e6669c8f436094cfbd80f3d6bc07f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 11 Mar 2018 17:42:16 +0100 Subject: [PATCH 238/291] Let's not do immediate flips in non-buffered. Should help #10395 --- Core/HLE/sceDisplay.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index ce25a55351..8c7fd13597 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -863,7 +863,9 @@ void __DisplaySetFramebuf(u32 topaddr, int linesize, int pixelFormat, int sync) framebuf = fbstate; gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.stride, framebuf.fmt); // IMMEDIATE means that the buffer is fine. We can just flip immediately. - if (!flippedThisFrame) + // Doing it in non-buffered though creates problems (black screen) on occasion though + // so let's not. + if (!flippedThisFrame && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) __DisplayFlip(0); } else { // Delay the write until vblank From d8651fd85b2484dee06c346a185f81cb0085a451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Mar 2018 11:07:51 +0100 Subject: [PATCH 239/291] Combine the lightAngle and spotCoef float uniforms into one float2. Saves 64 bytes from the light uniform buffer, making it an even 512. Probably a very small perf optimization. --- GPU/Common/ShaderUniforms.cpp | 4 ++-- GPU/Common/ShaderUniforms.h | 21 ++++++++------------- GPU/Directx9/ShaderManagerDX9.cpp | 4 ++-- GPU/Directx9/VertexShaderGeneratorDX9.cpp | 7 +++---- GPU/Directx9/VertexShaderGeneratorDX9.h | 11 +++++------ GPU/GLES/ShaderManagerGLES.cpp | 16 ++++++++++------ GPU/GLES/ShaderManagerGLES.h | 3 +-- GPU/GLES/VertexShaderGeneratorGLES.cpp | 7 +++---- GPU/Vulkan/VertexShaderGeneratorVulkan.cpp | 4 ++-- 9 files changed, 36 insertions(+), 41 deletions(-) diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 302c930673..5e0927410d 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -238,8 +238,8 @@ void LightUpdateUniforms(UB_VS_Lights *ub, uint64_t dirtyUniforms) { } ExpandFloat24x3ToFloat4(ub->ldir[i], &gstate.ldir[i * 3]); ExpandFloat24x3ToFloat4(ub->latt[i], &gstate.latt[i * 3]); - CopyFloat1To4(ub->lightAngle[i], getFloat24(gstate.lcutoff[i])); - CopyFloat1To4(ub->lightSpotCoef[i], getFloat24(gstate.lconv[i])); + float lightAngle_spotCoef[2] = { getFloat24(gstate.lcutoff[i]), getFloat24(gstate.lconv[i]) }; + CopyFloat2To4(ub->lightAngle_SpotCoef[i], lightAngle_spotCoef); Uint8x3ToFloat4(ub->lightAmbient[i], gstate.lcolor[i * 3]); Uint8x3ToFloat4(ub->lightDiffuse[i], gstate.lcolor[i * 3 + 1]); Uint8x3ToFloat4(ub->lightSpecular[i], gstate.lcolor[i * 3 + 2]); diff --git a/GPU/Common/ShaderUniforms.h b/GPU/Common/ShaderUniforms.h index 82bc27a33b..9e7d028c7a 100644 --- a/GPU/Common/ShaderUniforms.h +++ b/GPU/Common/ShaderUniforms.h @@ -93,7 +93,8 @@ R"( float4x4 u_proj; float2 u_texclampoff; )"; -// 576 bytes. Can we get down to 512? +// 512 bytes. Would like to shrink more. Some colors only have 8-bit precision and we expand +// them to float unnecessarily, could just as well expand in the shader. struct UB_VS_Lights { float ambientColor[4]; float materialDiffuse[4]; @@ -102,8 +103,7 @@ struct UB_VS_Lights { float lpos[4][4]; float ldir[4][4]; float latt[4][4]; - float lightAngle[4][4]; // TODO: Merge with lightSpotCoef, use .xy - float lightSpotCoef[4][4]; + float lightAngle_SpotCoef[4][4]; // TODO: Merge with lightSpotCoef, use .xy float lightAmbient[4][4]; float lightDiffuse[4][4]; float lightSpecular[4][4]; @@ -117,8 +117,7 @@ R"( vec4 u_ambient; vec3 pos[4]; vec3 dir[4]; vec3 att[4]; - float angle[4]; - float spotCoef[4]; + vec2 angle_spotCoef[4]; vec3 ambient[4]; vec3 diffuse[4]; vec3 specular[4]; @@ -142,14 +141,10 @@ R"( float4 u_ambient; float3 u_lightatt1; float3 u_lightatt2; float3 u_lightatt3; - float4 u_lightangle0; - float4 u_lightangle1; - float4 u_lightangle2; - float4 u_lightangle3; - float4 u_lightspotCoef0; - float4 u_lightspotCoef1; - float4 u_lightspotCoef2; - float4 u_lightspotCoef3; + float4 u_lightangle_spotCoef0; + float4 u_lightangle_spotCoef1; + float4 u_lightangle_spotCoef2; + float4 u_lightangle_spotCoef3; float3 u_lightambient0; float3 u_lightambient1; float3 u_lightambient2; diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 291446017f..10e128d620 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -456,8 +456,8 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { } VSSetFloat24Uniform3(CONST_VS_LIGHTDIR + i, &gstate.ldir[i * 3]); VSSetFloat24Uniform3(CONST_VS_LIGHTATT + i, &gstate.latt[i * 3]); - VSSetFloat(CONST_VS_LIGHTANGLE + i, getFloat24(gstate.lcutoff[i])); - VSSetFloat(CONST_VS_LIGHTSPOTCOEF + i, getFloat24(gstate.lconv[i])); + float angle_spotCoef[4] = { getFloat24(gstate.lcutoff[i]), getFloat24(gstate.lconv[i]) }; + VSSetFloatUniform4(CONST_VS_LIGHTANGLE_SPOTCOEF + i, angle_spotCoef); VSSetColorUniform3(CONST_VS_LIGHTAMBIENT + i, gstate.lcolor[i * 3]); VSSetColorUniform3(CONST_VS_LIGHTDIFFUSE + i, gstate.lcolor[i * 3 + 1]); VSSetColorUniform3(CONST_VS_LIGHTSPECULAR + i, gstate.lcolor[i * 3 + 2]); diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.cpp b/GPU/Directx9/VertexShaderGeneratorDX9.cpp index 4c2b5df7f1..69cdeb89aa 100644 --- a/GPU/Directx9/VertexShaderGeneratorDX9.cpp +++ b/GPU/Directx9/VertexShaderGeneratorDX9.cpp @@ -127,8 +127,7 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage if (type == GE_LIGHTTYPE_SPOT || type == GE_LIGHTTYPE_UNKNOWN) { WRITE(p, "float3 u_lightdir%i : register(c%i);\n", i, CONST_VS_LIGHTDIR + i); - WRITE(p, "float4 u_lightangle%i : register(c%i);\n", i, CONST_VS_LIGHTANGLE + i); - WRITE(p, "float4 u_lightspotCoef%i : register(c%i);\n", i, CONST_VS_LIGHTSPOTCOEF + i); + WRITE(p, "float4 u_lightangle_spotCoef%i : register(c%i);\n", i, CONST_VS_LIGHTANGLE_SPOTCOEF + i); } WRITE(p, "float3 u_lightambient%i : register(c%i);\n", i, CONST_VS_LIGHTAMBIENT + i); WRITE(p, "float3 u_lightdiffuse%i : register(c%i);\n", i, CONST_VS_LIGHTDIFFUSE + i); @@ -567,8 +566,8 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage case GE_LIGHTTYPE_SPOT: case GE_LIGHTTYPE_UNKNOWN: WRITE(p, " float angle%i = dot(normalize(u_lightdir%i), toLight);\n", i, i); - WRITE(p, " if (angle%i >= u_lightangle%i.x) {\n", i, i); - WRITE(p, " lightScale = clamp(1.0 / dot(u_lightatt%i, float3(1.0, distance, distance*distance)), 0.0, 1.0) * pow(angle%i, u_lightspotCoef%i.x);\n", i, i, i); + WRITE(p, " if (angle%i >= u_lightangle_spotCoef%i.x) {\n", i, i); + WRITE(p, " lightScale = clamp(1.0 / dot(u_lightatt%i, float3(1.0, distance, distance*distance)), 0.0, 1.0) * pow(angle%i, u_lightangle_spotCoef%i.y);\n", i, i, i); WRITE(p, " } else {\n"); WRITE(p, " lightScale = 0.0;\n"); WRITE(p, " }\n"); diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.h b/GPU/Directx9/VertexShaderGeneratorDX9.h index 062e4a1dcb..a76a5ec5ed 100644 --- a/GPU/Directx9/VertexShaderGeneratorDX9.h +++ b/GPU/Directx9/VertexShaderGeneratorDX9.h @@ -39,12 +39,11 @@ namespace DX9 { CONST_VS_LIGHTPOS = 24, CONST_VS_LIGHTDIR = 28, CONST_VS_LIGHTATT = 32, - CONST_VS_LIGHTANGLE = 36, - CONST_VS_LIGHTSPOTCOEF = 40, - CONST_VS_LIGHTDIFFUSE = 44, - CONST_VS_LIGHTSPECULAR = 48, - CONST_VS_LIGHTAMBIENT = 52, - CONST_VS_DEPTHRANGE = 56, + CONST_VS_LIGHTANGLE_SPOTCOEF = 36, + CONST_VS_LIGHTDIFFUSE = 40, + CONST_VS_LIGHTSPECULAR = 44, + CONST_VS_LIGHTAMBIENT = 48, + CONST_VS_DEPTHRANGE = 52, }; }; diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index d1e6afb5d6..746d2c4f7c 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -127,11 +127,9 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, queries.push_back({ &u_lightdir[i], lightdir_names[i] }); static const char * const lightatt_names[4] = { "u_lightatt0", "u_lightatt1", "u_lightatt2", "u_lightatt3", }; queries.push_back({ &u_lightatt[i], lightatt_names[i] }); - static const char * const lightangle_names[4] = { "u_lightangle0", "u_lightangle1", "u_lightangle2", "u_lightangle3", }; - queries.push_back({ &u_lightangle[i], lightangle_names[i] }); + static const char * const lightangle_spotCoef_names[4] = { "u_lightangle_spotCoef0", "u_lightangle_spotCoef1", "u_lightangle_spotCoef2", "u_lightangle_spotCoef3", }; + queries.push_back({ &u_lightangle_spotCoef[i], lightangle_spotCoef_names[i] }); - static const char * const lightspotCoef_names[4] = { "u_lightspotCoef0", "u_lightspotCoef1", "u_lightspotCoef2", "u_lightspotCoef3", }; - queries.push_back({ &u_lightspotCoef[i], lightspotCoef_names[i] }); static const char * const lightambient_names[4] = { "u_lightambient0", "u_lightambient1", "u_lightambient2", "u_lightambient3", }; queries.push_back({ &u_lightambient[i], lightambient_names[i] }); static const char * const lightdiffuse_names[4] = { "u_lightdiffuse0", "u_lightdiffuse1", "u_lightdiffuse2", "u_lightdiffuse3", }; @@ -176,6 +174,10 @@ static inline void SetFloatUniform(GLRenderManager *render, GLint *uniform, floa render->SetUniformF(uniform, 1, &value); } +static inline void SetFloatUniform2(GLRenderManager *render, GLint *uniform, float value[2]) { + render->SetUniformF(uniform, 2, value); +} + static inline void SetColorUniform3(GLRenderManager *render, GLint *uniform, u32 color) { float f[4]; Uint8x4ToFloat4(f, color); @@ -516,8 +518,10 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) { } if (u_lightdir[i] != -1) SetFloat24Uniform3(render_, &u_lightdir[i], &gstate.ldir[i * 3]); if (u_lightatt[i] != -1) SetFloat24Uniform3(render_, &u_lightatt[i], &gstate.latt[i * 3]); - if (u_lightangle[i] != -1) SetFloatUniform(render_, &u_lightangle[i], getFloat24(gstate.lcutoff[i])); - if (u_lightspotCoef[i] != -1) SetFloatUniform(render_, &u_lightspotCoef[i], getFloat24(gstate.lconv[i])); + if (u_lightangle_spotCoef[i] != -1) { + float lightangle_spotCoef[2] = { getFloat24(gstate.lcutoff[i]), getFloat24(gstate.lconv[i]) }; + SetFloatUniform2(render_, &u_lightangle_spotCoef[i], lightangle_spotCoef); + } if (u_lightambient[i] != -1) SetColorUniform3(render_, &u_lightambient[i], gstate.lcolor[i * 3]); if (u_lightdiffuse[i] != -1) SetColorUniform3(render_, &u_lightdiffuse[i], gstate.lcolor[i * 3 + 1]); if (u_lightspecular[i] != -1) SetColorUniform3(render_, &u_lightspecular[i], gstate.lcolor[i * 3 + 2]); diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index 981b63a476..7f19a77e28 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -99,8 +99,7 @@ public: int u_lightpos[4]; int u_lightdir[4]; int u_lightatt[4]; // attenuation - int u_lightangle[4]; // spotlight cone angle (cosine) - int u_lightspotCoef[4]; // spotlight dropoff + int u_lightangle_spotCoef[4]; // spotlight cone angle (cosine) (x), spotlight dropoff (y) int u_lightdiffuse[4]; // each light consist of vec4[3] int u_lightspecular[4]; // attenuation int u_lightambient[4]; // attenuation diff --git a/GPU/GLES/VertexShaderGeneratorGLES.cpp b/GPU/GLES/VertexShaderGeneratorGLES.cpp index d5357c72e4..a528ca9233 100644 --- a/GPU/GLES/VertexShaderGeneratorGLES.cpp +++ b/GPU/GLES/VertexShaderGeneratorGLES.cpp @@ -251,8 +251,7 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, if (type == GE_LIGHTTYPE_SPOT || type == GE_LIGHTTYPE_UNKNOWN) { WRITE(p, "uniform mediump vec3 u_lightdir%i;\n", i); - WRITE(p, "uniform mediump float u_lightangle%i;\n", i); - WRITE(p, "uniform mediump float u_lightspotCoef%i;\n", i); + WRITE(p, "uniform mediump vec2 u_lightangle_spotCoef%i;\n", i); } WRITE(p, "uniform lowp vec3 u_lightambient%i;\n", i); WRITE(p, "uniform lowp vec3 u_lightdiffuse%i;\n", i); @@ -646,8 +645,8 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, case GE_LIGHTTYPE_SPOT: case GE_LIGHTTYPE_UNKNOWN: WRITE(p, " angle = dot(normalize(u_lightdir%i), toLight);\n", i); - WRITE(p, " if (angle >= u_lightangle%i) {\n", i); - WRITE(p, " lightScale = clamp(1.0 / dot(u_lightatt%i, vec3(1.0, distance, distance*distance)), 0.0, 1.0) * pow(angle, u_lightspotCoef%i);\n", i, i); + WRITE(p, " if (angle >= u_lightangle_spotCoef%i.x) {\n", i); + WRITE(p, " lightScale = clamp(1.0 / dot(u_lightatt%i, vec3(1.0, distance, distance*distance)), 0.0, 1.0) * pow(angle, u_lightangle_spotCoef%i.y);\n", i, i); WRITE(p, " } else {\n"); WRITE(p, " lightScale = 0.0;\n"); WRITE(p, " }\n"); diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp index e4aa9e729c..4627118ab5 100644 --- a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp @@ -513,8 +513,8 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *use case GE_LIGHTTYPE_SPOT: case GE_LIGHTTYPE_UNKNOWN: WRITE(p, " float angle%i = dot(normalize(light.dir[%i]), toLight);\n", i, i); - WRITE(p, " if (angle%i >= light.angle[%i]) {\n", i, i); - WRITE(p, " lightScale = clamp(1.0 / dot(light.att[%i], vec3(1.0, distance, distance*distance)), 0.0, 1.0) * pow(angle%i, light.spotCoef[%i]);\n", i, i, i); + WRITE(p, " if (angle%i >= light.angle_spotCoef[%i].x) {\n", i, i); + WRITE(p, " lightScale = clamp(1.0 / dot(light.att[%i], vec3(1.0, distance, distance*distance)), 0.0, 1.0) * pow(angle%i, light.angle_spotCoef[%i].y);\n", i, i, i); WRITE(p, " } else {\n"); WRITE(p, " lightScale = 0.0;\n"); WRITE(p, " }\n"); From cd75c46d477e0aa9d4dc27247744ee4ca0449063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Mar 2018 11:58:51 +0100 Subject: [PATCH 240/291] Sort Vulkan function pointers by use. Might save us a cacheline or two during command submission.. --- Common/Vulkan/VulkanLoader.cpp | 41 +++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/Common/Vulkan/VulkanLoader.cpp b/Common/Vulkan/VulkanLoader.cpp index 72a3237f04..907f2d61e8 100644 --- a/Common/Vulkan/VulkanLoader.cpp +++ b/Common/Vulkan/VulkanLoader.cpp @@ -113,16 +113,12 @@ PFN_vkDestroyCommandPool vkDestroyCommandPool; PFN_vkResetCommandPool vkResetCommandPool; PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; PFN_vkFreeCommandBuffers vkFreeCommandBuffers; -PFN_vkBeginCommandBuffer vkBeginCommandBuffer; -PFN_vkEndCommandBuffer vkEndCommandBuffer; -PFN_vkResetCommandBuffer vkResetCommandBuffer; + +// Used frequently PFN_vkCmdBindPipeline vkCmdBindPipeline; PFN_vkCmdSetViewport vkCmdSetViewport; PFN_vkCmdSetScissor vkCmdSetScissor; -PFN_vkCmdSetLineWidth vkCmdSetLineWidth; -PFN_vkCmdSetDepthBias vkCmdSetDepthBias; PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants; -PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds; PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask; PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask; PFN_vkCmdSetStencilReference vkCmdSetStencilReference; @@ -131,34 +127,43 @@ PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer; PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers; PFN_vkCmdDraw vkCmdDraw; PFN_vkCmdDrawIndexed vkCmdDrawIndexed; -PFN_vkCmdDrawIndirect vkCmdDrawIndirect; -PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect; -PFN_vkCmdDispatch vkCmdDispatch; -PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect; +PFN_vkCmdClearAttachments vkCmdClearAttachments; +PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; +PFN_vkCmdPushConstants vkCmdPushConstants; + +// Every frame to a few times per frame +PFN_vkBeginCommandBuffer vkBeginCommandBuffer; +PFN_vkEndCommandBuffer vkEndCommandBuffer; +PFN_vkResetCommandBuffer vkResetCommandBuffer; +PFN_vkCmdSetEvent vkCmdSetEvent; +PFN_vkCmdResetEvent vkCmdResetEvent; +PFN_vkCmdWaitEvents vkCmdWaitEvents; +PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass; +PFN_vkCmdEndRenderPass vkCmdEndRenderPass; PFN_vkCmdCopyBuffer vkCmdCopyBuffer; PFN_vkCmdCopyImage vkCmdCopyImage; PFN_vkCmdBlitImage vkCmdBlitImage; PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage; PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer; + +PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds; +PFN_vkCmdSetLineWidth vkCmdSetLineWidth; +PFN_vkCmdSetDepthBias vkCmdSetDepthBias; +PFN_vkCmdDrawIndirect vkCmdDrawIndirect; +PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect; +PFN_vkCmdDispatch vkCmdDispatch; +PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect; PFN_vkCmdUpdateBuffer vkCmdUpdateBuffer; PFN_vkCmdFillBuffer vkCmdFillBuffer; PFN_vkCmdClearColorImage vkCmdClearColorImage; PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage; -PFN_vkCmdClearAttachments vkCmdClearAttachments; PFN_vkCmdResolveImage vkCmdResolveImage; -PFN_vkCmdSetEvent vkCmdSetEvent; -PFN_vkCmdResetEvent vkCmdResetEvent; -PFN_vkCmdWaitEvents vkCmdWaitEvents; -PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; PFN_vkCmdBeginQuery vkCmdBeginQuery; PFN_vkCmdEndQuery vkCmdEndQuery; PFN_vkCmdResetQueryPool vkCmdResetQueryPool; PFN_vkCmdWriteTimestamp vkCmdWriteTimestamp; PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults; -PFN_vkCmdPushConstants vkCmdPushConstants; -PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass; PFN_vkCmdNextSubpass vkCmdNextSubpass; -PFN_vkCmdEndRenderPass vkCmdEndRenderPass; PFN_vkCmdExecuteCommands vkCmdExecuteCommands; #ifdef __ANDROID__ From 2a438d6e03958369240eb67bc22987a47c437230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Mar 2018 20:07:31 +0100 Subject: [PATCH 241/291] Fix VSync on Windows. Should fix #10711 --- Windows/GPU/WindowsGLContext.cpp | 15 +++++++++------ ext/native/thin3d/GLRenderManager.cpp | 6 ++++++ ext/native/thin3d/GLRenderManager.h | 16 ++++++++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 7bed8d1e69..8feae44307 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -332,8 +332,6 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) { hRC = m_hrc; - SwapInterval(0); - if (g_Config.bGfxDebugOutput) { if (wglewIsSupported("GL_KHR_debug") == 1) { glGetError(); @@ -375,16 +373,21 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) { renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); // if we get this far, there will always be a GLSL compiler capable of compiling these. - renderManager_->SetSwapFunction([&]() {::SwapBuffers(hDC); }); assert(success); + renderManager_->SetSwapFunction([&]() {::SwapBuffers(hDC); }); + if (wglSwapIntervalEXT) { + // glew loads wglSwapIntervalEXT if available + renderManager_->SetSwapIntervalFunction([&](int interval) { + wglSwapIntervalEXT(interval); + }); + } CHECK_GL_ERROR_IF_DEBUG(); return true; // Success } void WindowsGLContext::SwapInterval(int interval) { - // glew loads wglSwapIntervalEXT if available - if (wglSwapIntervalEXT) - wglSwapIntervalEXT(interval); + // Delegate to the render manager to make sure it's done on the right thread. + renderManager_->SwapInterval(interval); } void WindowsGLContext::Shutdown() { diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index e126fd34e8..31e571c295 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -436,6 +436,12 @@ void GLRenderManager::EndSubmitFrame(int frame) { Submit(frame, true); if (!frameData.skipSwap) { + if (swapIntervalChanged_) { + swapIntervalChanged_ = false; + if (swapIntervalFunction_) { + swapIntervalFunction_(swapInterval_); + } + } if (swapFunction_) { swapFunction_(); } diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 11b93dafd9..5cb4e54e61 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -682,6 +682,7 @@ public: void RegisterPushBuffer(int frame, GLPushBuffer *buffer) { frameData_[frame].activePushBuffers.insert(buffer); } + void UnregisterPushBuffer(int frame, GLPushBuffer *buffer) { auto iter = frameData_[frame].activePushBuffers.find(buffer); _assert_(iter != frameData_[frame].activePushBuffers.end()); @@ -692,6 +693,17 @@ public: swapFunction_ = swapFunction; } + void SetSwapIntervalFunction(std::function swapIntervalFunction) { + swapIntervalFunction_ = swapIntervalFunction; + } + + void SwapInterval(int interval) { + if (interval != swapInterval_) { + swapInterval_ = interval; + swapIntervalChanged_ = true; + } + } + void StopThread(); bool SawOutOfMemory() { @@ -765,8 +777,12 @@ private: int curFrame_ = 0; std::function swapFunction_; + std::function swapIntervalFunction_; GLBufferStrategy bufferStrategy_ = GLBufferStrategy::SUBDATA; + int swapInterval_ = 0; + bool swapIntervalChanged_ = true; + int targetWidth_ = 0; int targetHeight_ = 0; }; From ad37e7ce451e475b61450dbefc42767f5c4eff8c Mon Sep 17 00:00:00 2001 From: Romain Graillot Date: Mon, 12 Mar 2018 23:11:58 +0100 Subject: [PATCH 242/291] Fix crash happening with glGetFloatv on GPDXD devices --- ext/native/thin3d/GLQueueRunner.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 93821b953f..46850f3c70 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -22,7 +22,12 @@ extern void bindDefaultFBO(); GLuint g_defaultFBO = 0; void GLQueueRunner::CreateDeviceObjects() { - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel_); + if (gl_extensions.EXT_texture_filter_anisotropic) { + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel_); + } else { + maxAnisotropyLevel_ = 0.0f; + } + if (gl_extensions.ARB_vertex_array_object) { glGenVertexArrays(1, &globalVAO_); } From 88e01c79440b1c4ac6ca17bce32f5e2344726e0e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 12 Mar 2018 18:06:46 -0700 Subject: [PATCH 243/291] UI: Show more detailed loading status. It's sometimes taking longer, so this may make it easier to identify. See #10673. --- Core/HLE/sceKernelModule.cpp | 5 +++++ Core/System.cpp | 15 +++++++++++++++ Core/System.h | 3 +++ GPU/GLES/ShaderManagerGLES.cpp | 5 ++++- UI/EmuScreen.cpp | 2 +- 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index adda9bd383..ff9826ebe9 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1588,6 +1588,8 @@ void __KernelLoadReset() { bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_string) { SceKernelLoadExecParam param; + PSP_SetLoading("Loading game..."); + if (paramPtr) Memory::ReadStruct(paramPtr, ¶m); else @@ -1626,6 +1628,7 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str pspFileSystem.ReadFile(handle, temp, (size_t)info.size); + PSP_SetLoading("Loading modules..."); Module *module = __KernelLoadModule(temp, (size_t)info.size, 0, error_string); if (!module || module->isFake) { @@ -1666,6 +1669,7 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str if (module->nm.module_start_thread_stacksize != 0) option.stacksize = module->nm.module_start_thread_stacksize; + PSP_SetLoading("Starting modules..."); if (paramPtr) __KernelStartModule(module, param.args, (const char*)param_argp, &option); else @@ -1682,6 +1686,7 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str bool __KernelLoadGEDump(const std::string &base_filename, std::string *error_string) { __KernelLoadReset(); + PSP_SetLoading("Generating code..."); mipsr4k.pc = PSP_GetUserMemoryBase(); diff --git a/Core/System.cpp b/Core/System.cpp index 772f00e877..43aa2822b6 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -81,6 +81,8 @@ ParamSFOData g_paramSFO; static GlobalUIState globalUIState; static CoreParameter coreParameter; static FileLoader *loadedFile; +static std::mutex loadingReasonLock; +static std::string loadingReason; bool audioInitialized; @@ -311,6 +313,7 @@ bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) { } coreParameter.errorString = ""; pspIsIniting = true; + PSP_SetLoading("Loading game..."); CPU_Init(); @@ -334,6 +337,7 @@ bool PSP_InitUpdate(std::string *error_string) { bool success = coreParameter.fileToStart != ""; *error_string = coreParameter.errorString; if (success && gpu == nullptr) { + PSP_SetLoading("Starting graphics..."); success = GPU_Init(coreParameter.graphicsContext, coreParameter.thin3d); if (!success) { PSP_Shutdown(); @@ -416,6 +420,17 @@ void PSP_RunLoopFor(int cycles) { PSP_RunLoopUntil(CoreTiming::GetTicks() + cycles); } +void PSP_SetLoading(const std::string &reason) { + std::lock_guard guard(loadingReasonLock); + loadingReason = reason; +} + +std::string PSP_GetLoading() { + std::lock_guard guard(loadingReasonLock); + return loadingReason; + +} + CoreParameter &PSP_CoreParameter() { return coreParameter; } diff --git a/Core/System.h b/Core/System.h index 6017e88cc5..a2a3ed5c48 100644 --- a/Core/System.h +++ b/Core/System.h @@ -73,6 +73,9 @@ void PSP_EndHostFrame(); void PSP_RunLoopUntil(u64 globalticks); void PSP_RunLoopFor(int cycles); +void PSP_SetLoading(const std::string &reason); +std::string PSP_GetLoading(); + // Call before PSP_BeginHostFrame() in order to not miss any GPU stats. void Core_UpdateDebugStats(bool collectStats); diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index bb06521ea6..7ee6adf12f 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -36,7 +36,8 @@ #include "Common/FileUtil.h" #include "Core/Config.h" #include "Core/Host.h" -#include "Core/Reporting.h" +#include "Core/Reporting.h"" +#include "Core/System.h" #include "GPU/Math3D.h" #include "GPU/GPUState.h" #include "GPU/ge_constants.h" @@ -885,6 +886,8 @@ bool ShaderManagerGLES::ContinuePrecompile(float sliceTime) { return true; } + PSP_SetLoading("Compiling shaders..."); + double start = real_time_now(); // Let's try to keep it under sliceTime if possible. double end = start + sliceTime; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index ab663a202b..256dbb62e1 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -861,7 +861,7 @@ void EmuScreen::CreateViews() { root_->Add(new OnScreenMessagesView(new AnchorLayoutParams((Size)bounds.w, (Size)bounds.h))); GameInfoBGView *loadingBG = root_->Add(new GameInfoBGView(gamePath_, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT))); - TextView *loadingTextView = root_->Add(new TextView(sc->T("Loading game..."), new AnchorLayoutParams(bounds.centerX(), bounds.centerY(), NONE, NONE, true))); + TextView *loadingTextView = root_->Add(new TextView(sc->T(PSP_GetLoading()), new AnchorLayoutParams(bounds.centerX(), bounds.centerY(), NONE, NONE, true))); static const int symbols[4] = { I_CROSS, I_CIRCLE, From 70481c9444fa1f9abf00cdcec20e60423a9ad35d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 13 Mar 2018 11:25:00 +0100 Subject: [PATCH 244/291] Fix the loading status. Prettify the loading screen by putting the status and spinner along the bottom edge. --- Core/PSPLoaders.cpp | 4 ++++ Core/System.cpp | 1 - UI/EmuScreen.cpp | 12 ++++++++---- UI/EmuScreen.h | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index 1a910edb05..7567d0b29c 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -16,8 +16,10 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include + #include "file/file_util.h" #include "util/text/utf8.h" +#include "thread/threadutil.h" #include "Common/FileUtil.h" #include "Common/StringUtils.h" @@ -253,6 +255,8 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) { INFO_LOG(LOADER,"Loading %s...", bootpath.c_str()); std::thread th([bootpath] { + setCurrentThreadName("ExecLoader"); + PSP_SetLoading("Loading executable..."); // TODO: We can't use the initial error_string pointer. bool success = __KernelLoadExec(bootpath.c_str(), 0, &PSP_CoreParameter().errorString); if (success && coreState == CORE_POWERUP) { diff --git a/Core/System.cpp b/Core/System.cpp index 43aa2822b6..cc559308c4 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -428,7 +428,6 @@ void PSP_SetLoading(const std::string &reason) { std::string PSP_GetLoading() { std::lock_guard guard(loadingReasonLock); return loadingReason; - } CoreParameter &PSP_CoreParameter() { diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index e8a51f6f35..339d79b532 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -861,17 +861,17 @@ void EmuScreen::CreateViews() { root_->Add(new OnScreenMessagesView(new AnchorLayoutParams((Size)bounds.w, (Size)bounds.h))); GameInfoBGView *loadingBG = root_->Add(new GameInfoBGView(gamePath_, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT))); - TextView *loadingTextView = root_->Add(new TextView(sc->T(PSP_GetLoading()), new AnchorLayoutParams(bounds.centerX(), bounds.centerY(), NONE, NONE, true))); + TextView *loadingTextView = root_->Add(new TextView(sc->T(PSP_GetLoading()), new AnchorLayoutParams(bounds.centerX(), NONE, NONE, 40, true))); static const int symbols[4] = { I_CROSS, I_CIRCLE, I_SQUARE, I_TRIANGLE }; - Spinner *loadingSpinner = root_->Add(new Spinner(symbols, ARRAY_SIZE(symbols), new AnchorLayoutParams(bounds.centerX(), bounds.centerY() + 64, NONE, NONE, true))); + Spinner *loadingSpinner = root_->Add(new Spinner(symbols, ARRAY_SIZE(symbols), new AnchorLayoutParams(NONE, NONE, 45, 45, true))); loadingSpinner_ = loadingSpinner; loadingTextView->SetShadow(true); - loadingView_ = loadingTextView; + loadingTextView_ = loadingTextView; loadingViewColor_ = loadingTextView->AddTween(new CallbackColorTween(0x00FFFFFF, 0x00FFFFFF, 0.2f, &bezierEaseInOut)); loadingViewColor_->SetCallback([loadingBG, loadingTextView, loadingSpinner](View *v, uint32_t c) { @@ -1109,6 +1109,10 @@ void EmuScreen::render() { DrawContext *thin3d = screenManager()->getDrawContext(); if (invalid_) { + // Loading, or after shutdown? + if (loadingTextView_->GetVisibility() == UI::V_VISIBLE) + loadingTextView_->SetText(PSP_GetLoading()); + // It's possible this might be set outside PSP_RunLoopFor(). // In this case, we need to double check it here. checkPowerDown(); @@ -1160,7 +1164,7 @@ void EmuScreen::render() { if (invalid_) return; - const bool hasVisibleUI = !osm.IsEmpty() || saveStatePreview_->GetVisibility() != UI::V_GONE || g_Config.bShowTouchControls || loadingView_->GetVisibility() == UI::V_VISIBLE; + const bool hasVisibleUI = !osm.IsEmpty() || saveStatePreview_->GetVisibility() != UI::V_GONE || g_Config.bShowTouchControls || loadingTextView_->GetVisibility() == UI::V_VISIBLE; const bool showDebugUI = g_Config.bShowDebugStats || g_Config.bShowDeveloperMenu || g_Config.bShowAudioDebug || g_Config.bShowFrameProfiler; if (hasVisibleUI || showDebugUI || g_Config.iShowFPSCounter != 0) { renderUI(); diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 755bc487ce..c5f95d515b 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -98,8 +98,8 @@ private: AsyncImageFileView *saveStatePreview_; int saveStateSlot_; - UI::View *loadingView_ = nullptr; UI::CallbackColorTween *loadingViewColor_ = nullptr; UI::VisibilityTween *loadingViewVisible_ = nullptr; UI::Spinner *loadingSpinner_ = nullptr; + UI::TextView *loadingTextView_ = nullptr; }; From 7a8310ae5e0a5dfc31d21157a9707b9979ad0af7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 13 Mar 2018 13:35:44 +0100 Subject: [PATCH 245/291] Tiny unification of code. Save the GL shader cache a bit less often. --- GPU/D3D11/GPU_D3D11.h | 8 -------- GPU/Directx9/GPU_DX9.h | 9 --------- GPU/GLES/GPU_GLES.cpp | 3 +-- GPU/GLES/GPU_GLES.h | 11 ++--------- GPU/GPUCommon.h | 8 ++++++++ GPU/Vulkan/GPU_Vulkan.h | 8 -------- 6 files changed, 11 insertions(+), 36 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index e716906f83..acb4dd3e07 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -51,11 +51,6 @@ public: void ClearShaderCache() override; - void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override { - primaryInfo = reportingPrimaryInfo_; - fullInfo = reportingFullInfo_; - } - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; @@ -89,7 +84,4 @@ private: int lastVsync_; int vertexCost_ = 0; - - std::string reportingPrimaryInfo_; - std::string reportingFullInfo_; }; diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index d72e2c4321..3fb4be032d 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -52,11 +52,6 @@ public: void ClearShaderCache() override; - void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override { - primaryInfo = reportingPrimaryInfo_; - fullInfo = reportingFullInfo_; - } - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; @@ -70,7 +65,6 @@ private: void Flush() { drawEngine_.Flush(); } - // void ApplyDrawState(int prim); void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); @@ -89,9 +83,6 @@ private: int lastVsync_; int vertexCost_ = 0; - - std::string reportingPrimaryInfo_; - std::string reportingFullInfo_; }; } // namespace DX9 diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 5b2e6445ac..41d03a3304 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -301,7 +301,6 @@ bool GPU_GLES::IsReady() { return shaderManagerGL_->ContinuePrecompile(); } -// Needs to be called on GPU thread, not reporting thread. void GPU_GLES::BuildReportingInfo() { GLRenderManager *render = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); @@ -421,7 +420,7 @@ void GPU_GLES::BeginFrame() { GPUCommon::BeginFrame(); // Save the cache from time to time. TODO: How often? - if (!shaderCachePath_.empty() && (gpuStats.numFlips & 1023) == 0) { + if (!shaderCachePath_.empty() && (gpuStats.numFlips & 4095) == 0) { shaderManagerGL_->Save(shaderCachePath_); } diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 4ea7a62064..6789491090 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -56,11 +56,6 @@ public: void ClearShaderCache() override; void CleanupBeforeUI() override; - void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override { - primaryInfo = reportingPrimaryInfo_; - fullInfo = reportingFullInfo_; - } - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; @@ -92,12 +87,10 @@ private: FragmentTestCacheGLES fragmentTestCache_; ShaderManagerGLES *shaderManagerGL_; + std::string shaderCachePath_; + #ifdef _WIN32 int lastVsync_; #endif int vertexCost_ = 0; - - std::string reportingPrimaryInfo_; - std::string reportingFullInfo_; - std::string shaderCachePath_; }; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 52bcec023f..afd0add47b 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -247,6 +247,11 @@ public: typedef void (GPUCommon::*CmdFunc)(u32 op, u32 diff); + void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override { + primaryInfo = reportingPrimaryInfo_; + fullInfo = reportingFullInfo_; + } + protected: void SetDrawType(DrawType type, GEPrimitiveType prim) { if (type != lastDraw_) { @@ -341,6 +346,9 @@ protected: int immCount_ = 0; GEPrimitiveType immPrim_; + std::string reportingPrimaryInfo_; + std::string reportingFullInfo_; + private: void FlushImm(); // Debug stats. diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 266fe01485..4357f854db 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -55,11 +55,6 @@ public: void ClearShaderCache() override; - void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override { - primaryInfo = reportingPrimaryInfo_; - fullInfo = reportingFullInfo_; - } - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; @@ -97,9 +92,6 @@ private: // Manages state and pipeline objects PipelineManagerVulkan *pipelineManager_; - std::string reportingPrimaryInfo_; - std::string reportingFullInfo_; - // Simple 2D drawing engine. Vulkan2D vulkan2D_; From f3040949a364b2db8adbe3ee41fed20ae0ba34b1 Mon Sep 17 00:00:00 2001 From: Carlos Estrague / Mrc_munir Date: Tue, 13 Mar 2018 20:16:41 +0100 Subject: [PATCH 246/291] Fix a typo extra " in some header Fix a typo introduced in https://github.com/hrydgard/ppsspp/pull/10715 --- GPU/GLES/ShaderManagerGLES.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index b1f40a6b61..399b01c1b0 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -36,7 +36,7 @@ #include "Common/FileUtil.h" #include "Core/Config.h" #include "Core/Host.h" -#include "Core/Reporting.h"" +#include "Core/Reporting.h" #include "Core/System.h" #include "GPU/Math3D.h" #include "GPU/GPUState.h" From ba5208efaa4676c1ee0ce199074f74d6fdceb22b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 14 Mar 2018 00:06:38 +0100 Subject: [PATCH 247/291] GL: Fix bug where we could crash if a readback happened at the same time as a buffer expansion. --- ext/native/thin3d/GLRenderManager.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index 31e571c295..d5f648b86a 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -455,15 +455,18 @@ void GLRenderManager::Run(int frame) { BeginSubmitFrame(frame); FrameData &frameData = frameData_[frame]; - for (auto iter : frameData.activePushBuffers) { - iter->Flush(); - iter->UnmapDevice(); - } auto &stepsOnThread = frameData_[frame].steps; auto &initStepsOnThread = frameData_[frame].initSteps; // queueRunner_.LogSteps(stepsOnThread); queueRunner_.RunInitSteps(initStepsOnThread); + + // Run this after RunInitSteps so any fresh GLRBuffers for the pushbuffers can get created. + for (auto iter : frameData.activePushBuffers) { + iter->Flush(); + iter->UnmapDevice(); + } + queueRunner_.RunSteps(stepsOnThread); stepsOnThread.clear(); initStepsOnThread.clear(); @@ -601,6 +604,7 @@ void GLPushBuffer::Flush() { if (!buffers_[buf_].deviceMemory && writePtr_) { auto &info = buffers_[buf_]; if (info.flushOffset != 0) { + assert(info.buffer->buffer); glBindBuffer(target_, info.buffer->buffer); glBufferSubData(target_, 0, info.flushOffset, info.localMemory); } From 3cd92b4d90cdd0045a3d6200f0d4d45a9ce8c8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 15 Mar 2018 16:10:12 +0100 Subject: [PATCH 248/291] Vulkan: Add a (disabled) facility to force image layouts to GENERAL, for debugging barrier issues --- Common/Vulkan/VulkanContext.cpp | 18 +++++ Common/Vulkan/VulkanContext.h | 6 ++ GPU/Vulkan/DrawEngineVulkan.cpp | 10 ++- GPU/Vulkan/VulkanUtil.cpp | 9 ++- ext/native/thin3d/VulkanQueueRunner.cpp | 92 +++++++++++++++++++------ ext/native/thin3d/thin3d_vulkan.cpp | 4 ++ 6 files changed, 115 insertions(+), 24 deletions(-) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index 5a232f2fa9..b87bee1065 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -965,6 +965,24 @@ void TransitionImageLayout2(VkCommandBuffer cmd, VkImage image, int baseMip, int VkImageLayout oldImageLayout, VkImageLayout newImageLayout, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) { +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR + if (aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) { + // Hack to disable transaction elimination on ARM Mali. + if (oldImageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || oldImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + oldImageLayout = VK_IMAGE_LAYOUT_GENERAL; + if (newImageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || newImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + newImageLayout = VK_IMAGE_LAYOUT_GENERAL; + } +#endif +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_DEPTH_STENCIL + if (aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) { + // Hack to disable transaction elimination on ARM Mali. + if (oldImageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || oldImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + oldImageLayout = VK_IMAGE_LAYOUT_GENERAL; + if (newImageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || newImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + newImageLayout = VK_IMAGE_LAYOUT_GENERAL; + } +#endif VkImageMemoryBarrier image_memory_barrier{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; image_memory_barrier.srcAccessMask = srcAccessMask; image_memory_barrier.dstAccessMask = dstAccessMask; diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index 6e03b92caf..e452ac38b9 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -109,6 +109,12 @@ struct VulkanDeviceExtensions { bool DEDICATED_ALLOCATION; }; +// Useful for debugging on ARM Mali. This eliminates transaction elimination +// which can cause artifacts if you get barriers wrong (or if there are driver bugs). +// Cost is reduced performance on some GPU architectures. +// #define VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR +// #define VULKAN_USE_GENERAL_LAYOUT_FOR_DEPTH_STENCIL + // VulkanContext manages the device and swapchain, and deferred deletion of objects. class VulkanContext { public: diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 9cb39484de..71ab2fae78 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -432,8 +432,11 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView int n = 0; VkDescriptorImageInfo tex[2]{}; if (imageView) { - // TODO: Also support LAYOUT_GENERAL to be able to texture from framebuffers without transitioning them? +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR + tex[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL; +#else tex[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; +#endif tex[0].imageView = imageView; tex[0].sampler = sampler; writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -447,8 +450,11 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView } if (boundSecondary_) { - // TODO: Also support LAYOUT_GENERAL to be able to texture from framebuffers without transitioning them? +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR + tex[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL; +#else tex[1].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; +#endif tex[1].imageView = boundSecondary_; tex[1].sampler = samplerSecondary_; writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; diff --git a/GPU/Vulkan/VulkanUtil.cpp b/GPU/Vulkan/VulkanUtil.cpp index fa41eb4bfc..f262c40479 100644 --- a/GPU/Vulkan/VulkanUtil.cpp +++ b/GPU/Vulkan/VulkanUtil.cpp @@ -164,8 +164,11 @@ VkDescriptorSet Vulkan2D::GetDescriptorSet(VkImageView tex1, VkSampler sampler1, VkDescriptorImageInfo image1 = {}; VkDescriptorImageInfo image2 = {}; if (tex1) { - // TODO: Also support LAYOUT_GENERAL to be able to texture from framebuffers without transitioning them? +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR + image1.imageLayout = VK_IMAGE_LAYOUT_GENERAL; +#else image1.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; +#endif image1.imageView = tex1; image1.sampler = sampler1; writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -178,7 +181,11 @@ VkDescriptorSet Vulkan2D::GetDescriptorSet(VkImageView tex1, VkSampler sampler1, } if (tex2) { // TODO: Also support LAYOUT_GENERAL to be able to texture from framebuffers without transitioning them? +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR + image2.imageLayout = VK_IMAGE_LAYOUT_GENERAL; +#else image2.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; +#endif image2.imageView = tex2; image2.sampler = sampler2; writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 6c04fd3d30..235000821f 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -95,17 +95,26 @@ void VulkanQueueRunner::InitBackbufferRenderPass() { attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // Don't care about storing backbuffer Z - we clear it anyway. attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_DEPTH_STENCIL + attachments[1].initialLayout = VK_IMAGE_LAYOUT_GENERAL; + attachments[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL; +#else attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; +#endif attachments[1].flags = 0; VkAttachmentReference color_reference{}; color_reference.attachment = 0; +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR + color_reference.layout = VK_IMAGE_LAYOUT_GENERAL; +#else color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; +#endif VkAttachmentReference depth_reference{}; depth_reference.attachment = 1; - depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depth_reference.layout = attachments[1].finalLayout; VkSubpassDescription subpass{}; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; @@ -166,8 +175,13 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR + attachments[0].initialLayout = VK_IMAGE_LAYOUT_GENERAL; + attachments[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL; // TODO: Look into auto-transitioning to SAMPLED when appropriate. +#else attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // TODO: Look into auto-transitioning to SAMPLED when appropriate. +#endif attachments[0].flags = 0; attachments[1].format = vulkan_->GetDeviceInfo().preferredDepthStencilFormat; @@ -196,17 +210,22 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio } attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_DEPTH_STENCIL + attachments[1].initialLayout = VK_IMAGE_LAYOUT_GENERAL; + attachments[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL; +#else attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; +#endif attachments[1].flags = 0; VkAttachmentReference color_reference{}; color_reference.attachment = 0; - color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + color_reference.layout = attachments[0].finalLayout; VkAttachmentReference depth_reference{}; depth_reference.attachment = 1; - depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depth_reference.layout = attachments[1].finalLayout; VkSubpassDescription subpass{}; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; @@ -501,40 +520,35 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c // Transition the framebuffer if requested. // Don't need to transition it if VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL. if (fb && step.render.finalColorLayout != VK_IMAGE_LAYOUT_UNDEFINED && step.render.finalColorLayout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { - VkImageMemoryBarrier barrier{}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.oldLayout = fb->color.layout; - barrier.subresourceRange.layerCount = 1; - barrier.subresourceRange.levelCount = 1; - barrier.image = fb->color.image; - barrier.srcAccessMask = 0; - switch (barrier.oldLayout) { + VkAccessFlags srcAccessMask = 0; + VkAccessFlags dstAccessMask = 0; + switch (fb->color.layout) { case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; break; default: Crash(); } - barrier.newLayout = step.render.finalColorLayout; - switch (barrier.newLayout) { + switch (step.render.finalColorLayout) { case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + dstAccessMask = VK_ACCESS_SHADER_READ_BIT; break; case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; break; default: Crash(); } - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - // we're between passes so it's OK. // ARM Best Practices guide recommends these stage bits. - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier); - fb->color.layout = barrier.newLayout; + TransitionImageLayout2(cmd, fb->color.image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, + fb->color.layout, step.render.finalColorLayout, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + srcAccessMask, dstAccessMask); + fb->color.layout = step.render.finalColorLayout; } } @@ -833,6 +847,24 @@ void VulkanQueueRunner::SetupTransitionToTransferSrc(VKRImage &img, VkImageMemor barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; img.layout = barrier.newLayout; + + // NOTE: Must do this AFTER updating img.layout to avoid behaviour differences. +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR + if (aspect == VK_IMAGE_ASPECT_COLOR_BIT) { + if (barrier.oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || barrier.oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; + if (barrier.newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || barrier.newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + } +#endif +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_DEPTH_STENCIL + if (aspect != VK_IMAGE_ASPECT_COLOR_BIT) { + if (barrier.oldLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || barrier.oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; + if (barrier.newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || barrier.newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + } +#endif } void VulkanQueueRunner::SetupTransitionToTransferDst(VKRImage &img, VkImageMemoryBarrier &barrier, VkPipelineStageFlags &stage, VkImageAspectFlags aspect) { @@ -869,6 +901,24 @@ void VulkanQueueRunner::SetupTransitionToTransferDst(VKRImage &img, VkImageMemor barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; img.layout = barrier.newLayout; + + // NOTE: Must do this AFTER updating img.layout to avoid behaviour differences. +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR + if (aspect == VK_IMAGE_ASPECT_COLOR_BIT) { + if (barrier.oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || barrier.oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; + if (barrier.newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || barrier.newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + } +#endif +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_DEPTH_STENCIL + if (aspect != VK_IMAGE_ASPECT_COLOR_BIT) { + if (barrier.oldLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || barrier.oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; + if (barrier.newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || barrier.newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + } +#endif } void VulkanQueueRunner::PerformReadback(const VKRStep &step, VkCommandBuffer cmd) { diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 1f5660adfb..1899512bd3 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -859,7 +859,11 @@ VkDescriptorSet VKContext::GetOrCreateDescriptorSet(VkBuffer buf) { VkDescriptorImageInfo imageDesc; imageDesc.imageView = boundTextures_[0]->GetImageView(); imageDesc.sampler = boundSamplers_[0]->GetSampler(); +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR + imageDesc.imageLayout = VK_IMAGE_LAYOUT_GENERAL; +#else imageDesc.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; +#endif VkWriteDescriptorSet writes[2] = {}; writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; From df8dac4aae74e52aae1eeb3d7ede5ce81fbffa03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 16 Mar 2018 13:35:49 +0100 Subject: [PATCH 249/291] If the first renderpass is an empty clear, merge it into the next one that touches the same framebuffer. Works around #10723 in Wipeout. --- ext/native/thin3d/VulkanQueueRunner.cpp | 37 +++++++++++++++++++++++-- ext/native/thin3d/VulkanQueueRunner.h | 1 + 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 235000821f..fdeafcd6b2 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -255,11 +255,39 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vector &steps) { // Optimizes renderpasses, then sequences them. // Planned optimizations: - // * Push down empty "Clear/Store" renderpasses, and merge them with the first "Load/Store" to the same framebuffer. - // (These happen in Wipeout) // * Create copies of render target that are rendered to multiple times and textured from in sequence, and push those render passes // as early as possible in the frame (Wipeout billboards). + // Push down empty "Clear/Store" renderpasses, and merge them with the first "Load/Store" to the same framebuffer. + // Actually let's just bother with the first one for now. This affects Wipeout Pure. + if (steps.size() > 1 && steps[0]->stepType == VKRStepType::RENDER && + steps[0]->render.numDraws == 0 && + steps[0]->render.color == VKRRenderPassAction::CLEAR && + steps[0]->render.stencil == VKRRenderPassAction::CLEAR && + steps[0]->render.depth == VKRRenderPassAction::CLEAR) { + // Drop the first step, and merge it into the next step that touches the same framebuffer. + for (size_t i = 1; i < steps.size(); i++) { + if (steps[i]->stepType == VKRStepType::RENDER && + steps[i]->render.framebuffer == steps[0]->render.framebuffer) { + if (steps[i]->render.color != VKRRenderPassAction::CLEAR) { + steps[i]->render.color = VKRRenderPassAction::CLEAR; + steps[i]->render.clearColor = steps[0]->render.clearColor; + } + if (steps[i]->render.depth != VKRRenderPassAction::CLEAR) { + steps[i]->render.depth = VKRRenderPassAction::CLEAR; + steps[i]->render.clearDepth = steps[0]->render.clearDepth; + } + if (steps[i]->render.stencil != VKRRenderPassAction::CLEAR) { + steps[i]->render.stencil = VKRRenderPassAction::CLEAR; + steps[i]->render.clearStencil = steps[0]->render.clearStencil; + } + // Cheaply skip the first step. + steps[0]->stepType = VKRStepType::RENDER_SKIP; + break; + } + } + } + for (size_t i = 0; i < steps.size(); i++) { const VKRStep &step = *steps[i]; switch (step.stepType) { @@ -278,6 +306,8 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vector &steps) { case VKRStepType::READBACK_IMAGE: LogReadbackImage(step); break; + case VKRStepType::RENDER_SKIP: + ILOG("(skipped render pass)"); + break; } } } diff --git a/ext/native/thin3d/VulkanQueueRunner.h b/ext/native/thin3d/VulkanQueueRunner.h index 8257fa450a..f10326ff95 100644 --- a/ext/native/thin3d/VulkanQueueRunner.h +++ b/ext/native/thin3d/VulkanQueueRunner.h @@ -82,6 +82,7 @@ struct VkRenderData { enum class VKRStepType : uint8_t { RENDER, + RENDER_SKIP, COPY, BLIT, READBACK, From a08464eb77a478f4b2bfa1c5558d3bf9be91298b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 16 Mar 2018 14:57:41 +0100 Subject: [PATCH 250/291] Vulkan: Also check for empty clearing renderpasses later in the frame. --- ext/native/thin3d/VulkanQueueRunner.cpp | 53 ++++++++++++++----------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index fdeafcd6b2..2e4fd93f7d 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -260,30 +260,37 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vector 1 && steps[0]->stepType == VKRStepType::RENDER && - steps[0]->render.numDraws == 0 && - steps[0]->render.color == VKRRenderPassAction::CLEAR && - steps[0]->render.stencil == VKRRenderPassAction::CLEAR && - steps[0]->render.depth == VKRRenderPassAction::CLEAR) { - // Drop the first step, and merge it into the next step that touches the same framebuffer. - for (size_t i = 1; i < steps.size(); i++) { - if (steps[i]->stepType == VKRStepType::RENDER && - steps[i]->render.framebuffer == steps[0]->render.framebuffer) { - if (steps[i]->render.color != VKRRenderPassAction::CLEAR) { - steps[i]->render.color = VKRRenderPassAction::CLEAR; - steps[i]->render.clearColor = steps[0]->render.clearColor; + for (int j = 0; j < (int)steps.size() - 1; j++) { + if (steps.size() > 1 && steps[j]->stepType == VKRStepType::RENDER && + steps[j]->render.numDraws == 0 && + steps[j]->render.color == VKRRenderPassAction::CLEAR && + steps[j]->render.stencil == VKRRenderPassAction::CLEAR && + steps[j]->render.depth == VKRRenderPassAction::CLEAR) { + + //if (j != 0) + // __debugbreak(); + + // Drop the first step, and merge it into the next step that touches the same framebuffer. + for (size_t i = j + 1; i < steps.size(); i++) { + if (steps[i]->stepType == VKRStepType::RENDER && + steps[i]->render.framebuffer == steps[j]->render.framebuffer) { + if (steps[i]->render.color != VKRRenderPassAction::CLEAR) { + steps[i]->render.color = VKRRenderPassAction::CLEAR; + steps[i]->render.clearColor = steps[j]->render.clearColor; + } + if (steps[i]->render.depth != VKRRenderPassAction::CLEAR) { + steps[i]->render.depth = VKRRenderPassAction::CLEAR; + steps[i]->render.clearDepth = steps[j]->render.clearDepth; + } + if (steps[i]->render.stencil != VKRRenderPassAction::CLEAR) { + steps[i]->render.stencil = VKRRenderPassAction::CLEAR; + steps[i]->render.clearStencil = steps[j]->render.clearStencil; + } + // Cheaply skip the first step. + steps[j]->stepType = VKRStepType::RENDER_SKIP; + ILOG("Avoided a lone clear at step %d, merged it with step %d", (int)j, (int)i); + break; } - if (steps[i]->render.depth != VKRRenderPassAction::CLEAR) { - steps[i]->render.depth = VKRRenderPassAction::CLEAR; - steps[i]->render.clearDepth = steps[0]->render.clearDepth; - } - if (steps[i]->render.stencil != VKRRenderPassAction::CLEAR) { - steps[i]->render.stencil = VKRRenderPassAction::CLEAR; - steps[i]->render.clearStencil = steps[0]->render.clearStencil; - } - // Cheaply skip the first step. - steps[0]->stepType = VKRStepType::RENDER_SKIP; - break; } } } From c5ebb2d73f898508c758ca8cdfd3b5ed4eeebb46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 16 Mar 2018 14:58:25 +0100 Subject: [PATCH 251/291] Oops, remove logging --- ext/native/thin3d/VulkanQueueRunner.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 2e4fd93f7d..1206b74e5a 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -267,9 +267,6 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vectorrender.stencil == VKRRenderPassAction::CLEAR && steps[j]->render.depth == VKRRenderPassAction::CLEAR) { - //if (j != 0) - // __debugbreak(); - // Drop the first step, and merge it into the next step that touches the same framebuffer. for (size_t i = j + 1; i < steps.size(); i++) { if (steps[i]->stepType == VKRStepType::RENDER && @@ -288,7 +285,6 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vectorstepType = VKRStepType::RENDER_SKIP; - ILOG("Avoided a lone clear at step %d, merged it with step %d", (int)j, (int)i); break; } } From 4ee941dab1b813b82eeac3b306d3f246a2bcfd97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 16 Mar 2018 15:52:43 +0100 Subject: [PATCH 252/291] Vulkan: Fix bug where we didn't always reset dynamic state after readbacks. --- GPU/Common/FramebufferCommon.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index ff3a131190..c00afc1a26 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -2042,6 +2042,10 @@ void FramebufferManagerCommon::PackFramebufferSync_(VirtualFramebuffer *vfb, int DEBUG_LOG(G3D, "Reading framebuffer to mem, fb_address = %08x", fb_address); draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, x, y, w, h, destFormat, destPtr, vfb->fb_stride); + + // A new command buffer will begin after CopyFrameBufferToMemorySync, so we need to trigger + // updates of any dynamic command buffer state by dirtying some stuff. + gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE); gpuStats.numReadbacks++; } From 45464896d204d9f982cd755b68d451dd8cd92f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 16 Mar 2018 16:45:27 +0100 Subject: [PATCH 253/291] Update lang submodule --- assets/lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/lang b/assets/lang index 350f71780a..d0e02dbcf9 160000 --- a/assets/lang +++ b/assets/lang @@ -1 +1 @@ -Subproject commit 350f71780adaaec0261d68149c093c6e1d86e215 +Subproject commit d0e02dbcf91696daa996d7dd7ffe95d8a3443afa From 8dc85c1a606b3e63879a1c1825bb2d1203d5d1f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 16 Mar 2018 17:38:02 +0100 Subject: [PATCH 254/291] Vulkan pipeline: Merge a few property fields to a flags field. To make saving/loading them easier. --- GPU/Vulkan/DrawEngineVulkan.cpp | 8 ++++---- GPU/Vulkan/PipelineManagerVulkan.cpp | 12 +++++++----- GPU/Vulkan/PipelineManagerVulkan.h | 16 ++++++++++------ 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 71ab2fae78..601c7dc8ca 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -783,12 +783,12 @@ void DrawEngineVulkan::DoFlush() { BindShaderBlendTex(); // This might cause copies so important to do before BindPipeline. renderManager->BindPipeline(pipeline->pipeline); if (pipeline != lastPipeline_) { - if (lastPipeline_ && !lastPipeline_->useBlendConstant && pipeline->useBlendConstant) { + if (lastPipeline_ && !(lastPipeline_->UsesBlendConstant() && pipeline->UsesBlendConstant())) { gstate_c.Dirty(DIRTY_BLEND_STATE); } lastPipeline_ = pipeline; } - ApplyDrawStateLate(renderManager, false, 0, pipeline->useBlendConstant); + ApplyDrawStateLate(renderManager, false, 0, pipeline->UsesBlendConstant()); gstate_c.Clean(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE); lastPipeline_ = pipeline; @@ -887,12 +887,12 @@ void DrawEngineVulkan::DoFlush() { BindShaderBlendTex(); // This might cause copies so super important to do before BindPipeline. renderManager->BindPipeline(pipeline->pipeline); if (pipeline != lastPipeline_) { - if (lastPipeline_ && !lastPipeline_->useBlendConstant && pipeline->useBlendConstant) { + if (lastPipeline_ && !lastPipeline_->UsesBlendConstant() && pipeline->UsesBlendConstant()) { gstate_c.Dirty(DIRTY_BLEND_STATE); } lastPipeline_ = pipeline; } - ApplyDrawStateLate(renderManager, result.setStencil, result.stencilValue, pipeline->useBlendConstant); + ApplyDrawStateLate(renderManager, result.setStencil, result.stencilValue, pipeline->UsesBlendConstant()); gstate_c.Clean(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE); lastPipeline_ = pipeline; diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 06aa2ef80a..31b6d77f59 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -285,12 +285,14 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip VulkanPipeline *vulkanPipeline = new VulkanPipeline(); vulkanPipeline->pipeline = pipeline; - vulkanPipeline->uniformBlocks = UB_VS_FS_BASE; - vulkanPipeline->useBlendConstant = useBlendConstant; - vulkanPipeline->usesLines = key.topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST || key.topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; + vulkanPipeline->flags = PIPELINE_FLAG_USES_BASE_UB; + if (useBlendConstant) + vulkanPipeline->flags |= PIPELINE_FLAG_USES_BLEND_CONSTANT; + if (key.topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST || key.topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP) + vulkanPipeline->flags |= PIPELINE_FLAG_USES_LINES; if (useHwTransform) { if (vs->HasLights()) { - vulkanPipeline->uniformBlocks |= UB_VS_LIGHTS; + vulkanPipeline->flags |= PIPELINE_FLAG_USES_LIGHT_UB; } } return vulkanPipeline; @@ -489,7 +491,7 @@ void PipelineManagerVulkan::SetLineWidth(float lineWidth) { // Wipe all line-drawing pipelines. pipelines_.Iterate([&](const VulkanPipelineKey &key, VulkanPipeline *value) { - if (value->usesLines) { + if (value->UsesLines()) { vulkan_->Delete().QueueDeletePipeline(value->pipeline); delete value; pipelines_.Remove(key); diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index 846f9d84da..590cbd9cb5 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -54,17 +54,21 @@ struct VulkanPipelineKey { } }; -enum { - UB_VS_FS_BASE = (1 << 0), - UB_VS_LIGHTS = (1 << 1), +enum PipelineFlags { + PIPELINE_FLAG_USES_BASE_UB = (1 << 0), + PIPELINE_FLAG_USES_LIGHT_UB = (1 << 1), + PIPELINE_FLAG_USES_LINES = (1 << 2), + PIPELINE_FLAG_USES_BLEND_CONSTANT = (1 << 3), }; // Simply wraps a Vulkan pipeline, providing some metadata. struct VulkanPipeline { VkPipeline pipeline; - int uniformBlocks; // UB_ enum above. - bool useBlendConstant; - bool usesLines; + int flags; // PipelineFlags enum above. + + // Convenience. + bool UsesBlendConstant() const { return (flags & PIPELINE_FLAG_USES_BLEND_CONSTANT) != 0; } + bool UsesLines() const { return (flags & PIPELINE_FLAG_USES_LINES) != 0; } }; class VulkanContext; From 2d33d526b8b15f46ac0fe15ba182dae608a7cf13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 16 Mar 2018 20:38:05 +0100 Subject: [PATCH 255/291] Remove some remains of software skinning --- GPU/Common/VertexDecoderCommon.cpp | 2 +- GPU/Common/VertexDecoderCommon.h | 57 ---------------------------- GPU/D3D11/DrawEngineD3D11.cpp | 12 ------ GPU/Directx9/DrawEngineDX9.cpp | 10 ----- GPU/GLES/DrawEngineGLES.cpp | 2 - GPU/Vulkan/PipelineManagerVulkan.cpp | 6 --- 6 files changed, 1 insertion(+), 88 deletions(-) diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index bedd9c9186..ebb21a4938 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -72,7 +72,7 @@ int DecFmtSize(u8 fmt) { } void DecVtxFormat::ComputeID() { - id = w0fmt | (w1fmt << 4) | (uvfmt << 8) | (c0fmt << 12) | (c1fmt << 16) | (nrmfmt << 20) | (posfmt << 24); + id = uvfmt | (c0fmt << 4) | (c1fmt << 8) | (nrmfmt << 12) | (posfmt << 16); } void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound) { diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 17efcabb32..3c346c1cfb 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -67,8 +67,6 @@ enum { int DecFmtSize(u8 fmt); struct DecVtxFormat { - u8 w0fmt; u8 w0off; // first 4 weights - u8 w1fmt; u8 w1off; // second 4 weights u8 uvfmt; u8 uvoff; u8 c0fmt; u8 c0off; // First color u8 c1fmt; u8 c1off; @@ -346,61 +344,6 @@ public: } } - void ReadWeights(float weights[8]) const { - const float *f = (const float *)(data_ + decFmt_.w0off); - const u8 *b = (const u8 *)(data_ + decFmt_.w0off); - const u16 *s = (const u16 *)(data_ + decFmt_.w0off); - switch (decFmt_.w0fmt) { - case DEC_FLOAT_1: - case DEC_FLOAT_2: - case DEC_FLOAT_3: - case DEC_FLOAT_4: - for (int i = 0; i <= decFmt_.w0fmt - DEC_FLOAT_1; i++) - weights[i] = f[i]; - break; - case DEC_U8_1: weights[0] = b[0] * (1.f / 128.f); break; - case DEC_U8_2: for (int i = 0; i < 2; i++) weights[i] = b[i] * (1.f / 128.f); break; - case DEC_U8_3: for (int i = 0; i < 3; i++) weights[i] = b[i] * (1.f / 128.f); break; - case DEC_U8_4: for (int i = 0; i < 4; i++) weights[i] = b[i] * (1.f / 128.f); break; - case DEC_U16_1: weights[0] = s[0] * (1.f / 32768.f); break; - case DEC_U16_2: for (int i = 0; i < 2; i++) weights[i] = s[i] * (1.f / 32768.f); break; - case DEC_U16_3: for (int i = 0; i < 3; i++) weights[i] = s[i] * (1.f / 32768.f); break; - case DEC_U16_4: for (int i = 0; i < 4; i++) weights[i] = s[i] * (1.f / 32768.f); break; - default: - ERROR_LOG_REPORT_ONCE(fmtw0, G3D, "Reader: Unsupported W0 Format %d", decFmt_.w0fmt); - memset(weights, 0, sizeof(float) * 8); - break; - } - - f = (const float *)(data_ + decFmt_.w1off); - b = (const u8 *)(data_ + decFmt_.w1off); - s = (const u16 *)(data_ + decFmt_.w1off); - switch (decFmt_.w1fmt) { - case 0: - // It's fine for there to be w0 weights but not w1. - break; - case DEC_FLOAT_1: - case DEC_FLOAT_2: - case DEC_FLOAT_3: - case DEC_FLOAT_4: - for (int i = 0; i <= decFmt_.w1fmt - DEC_FLOAT_1; i++) - weights[i+4] = f[i]; - break; - case DEC_U8_1: weights[4] = b[0] * (1.f / 128.f); break; - case DEC_U8_2: for (int i = 0; i < 2; i++) weights[i+4] = b[i] * (1.f / 128.f); break; - case DEC_U8_3: for (int i = 0; i < 3; i++) weights[i+4] = b[i] * (1.f / 128.f); break; - case DEC_U8_4: for (int i = 0; i < 4; i++) weights[i+4] = b[i] * (1.f / 128.f); break; - case DEC_U16_1: weights[4] = s[0] * (1.f / 32768.f); break; - case DEC_U16_2: for (int i = 0; i < 2; i++) weights[i+4] = s[i] * (1.f / 32768.f); break; - case DEC_U16_3: for (int i = 0; i < 3; i++) weights[i+4] = s[i] * (1.f / 32768.f); break; - case DEC_U16_4: for (int i = 0; i < 4; i++) weights[i+4] = s[i] * (1.f / 32768.f); break; - default: - ERROR_LOG_REPORT_ONCE(fmtw1, G3D, "Reader: Unsupported W1 Format %d", decFmt_.w1fmt); - memset(weights + 4, 0, sizeof(float) * 4); - break; - } - } - bool hasColor0() const { return decFmt_.c0fmt != 0; } bool hasColor1() const { return decFmt_.c1fmt != 0; } bool hasNormal() const { return decFmt_.nrmfmt != 0; } diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 29273e04a2..35b81a3d89 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -204,18 +204,6 @@ ID3D11InputLayout *DrawEngineD3D11::SetupDecFmtForDraw(D3D11VertexShader *vshade D3D11_INPUT_ELEMENT_DESC VertexElements[8]; D3D11_INPUT_ELEMENT_DESC *VertexElement = &VertexElements[0]; - // Vertices Elements orders - // WEIGHT - if (decFmt.w0fmt != 0) { - VertexAttribSetup(VertexElement, decFmt.w0fmt, decFmt.w0off, "TEXCOORD", 1); - VertexElement++; - } - - if (decFmt.w1fmt != 0) { - VertexAttribSetup(VertexElement, decFmt.w1fmt, decFmt.w1off, "TEXCOORD", 2); - VertexElement++; - } - // TC if (decFmt.uvfmt != 0) { VertexAttribSetup(VertexElement, decFmt.uvfmt, decFmt.uvoff, "TEXCOORD", 0); diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 99ee183863..a19c1f4116 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -175,16 +175,6 @@ IDirect3DVertexDeclaration9 *DrawEngineDX9::SetupDecFmtForDraw(VSShader *vshader D3DVERTEXELEMENT9 *VertexElement = &VertexElements[0]; // Vertices Elements orders - // WEIGHT - if (decFmt.w0fmt != 0) { - VertexAttribSetup(VertexElement, decFmt.w0fmt, decFmt.w0off, D3DDECLUSAGE_TEXCOORD, 1); - VertexElement++; - } - - if (decFmt.w1fmt != 0) { - VertexAttribSetup(VertexElement, decFmt.w1fmt, decFmt.w1off, D3DDECLUSAGE_TEXCOORD, 2); - VertexElement++; - } // TC if (decFmt.uvfmt != 0) { diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 7fc17ea5c1..24c84b616a 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -217,8 +217,6 @@ GLRInputLayout *DrawEngineGLES::SetupDecFmtForDraw(LinkedShader *program, const } std::vector entries; - VertexAttribSetup(ATTR_W1, decFmt.w0fmt, decFmt.stride, decFmt.w0off, entries); - VertexAttribSetup(ATTR_W2, decFmt.w1fmt, decFmt.stride, decFmt.w1off, entries); VertexAttribSetup(ATTR_TEXCOORD, decFmt.uvfmt, decFmt.stride, decFmt.uvoff, entries); VertexAttribSetup(ATTR_COLOR0, decFmt.c0fmt, decFmt.stride, decFmt.c0off, entries); VertexAttribSetup(ATTR_COLOR1, decFmt.c1fmt, decFmt.stride, decFmt.c1off, entries); diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 31b6d77f59..e44ff9f83d 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -80,12 +80,6 @@ static void VertexAttribSetup(VkVertexInputAttributeDescription *attr, int fmt, // as we will only call this code when we need to create a new VkPipeline. static int SetupVertexAttribs(VkVertexInputAttributeDescription attrs[], const DecVtxFormat &decFmt) { int count = 0; - if (decFmt.w0fmt != 0) { - VertexAttribSetup(&attrs[count++], decFmt.w0fmt, decFmt.w0off, PspAttributeLocation::W1); - } - if (decFmt.w1fmt != 0) { - VertexAttribSetup(&attrs[count++], decFmt.w1fmt, decFmt.w1off, PspAttributeLocation::W2); - } if (decFmt.uvfmt != 0) { VertexAttribSetup(&attrs[count++], decFmt.uvfmt, decFmt.uvoff, PspAttributeLocation::TEXCOORD); } From 614cabb115e61f758fb16f732e162283a34c3932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 13 Mar 2018 23:22:21 +0100 Subject: [PATCH 256/291] Implement pipeline/shader cache for Vulkan, to avoid shader compile stutters on second and subsequent runs. The raw pipeline cache got pretty large. Instead, store IDs like GL. There's still a disabled option to store the pipeline cache objects. --- Common/Vulkan/VulkanContext.cpp | 11 -- Common/Vulkan/VulkanContext.h | 2 - GPU/Common/DrawEngineCommon.h | 4 +- GPU/Common/VertexDecoderCommon.cpp | 15 +++ GPU/Common/VertexDecoderCommon.h | 3 +- GPU/GLES/DrawEngineGLES.cpp | 2 +- GPU/GLES/GPU_GLES.cpp | 2 +- GPU/Vulkan/DrawEngineVulkan.cpp | 2 - GPU/Vulkan/GPU_Vulkan.cpp | 52 +++++++++ GPU/Vulkan/GPU_Vulkan.h | 5 + GPU/Vulkan/PipelineManagerVulkan.cpp | 164 +++++++++++++++++++++++++-- GPU/Vulkan/PipelineManagerVulkan.h | 18 ++- GPU/Vulkan/ShaderManagerVulkan.cpp | 96 +++++++++++++++- GPU/Vulkan/ShaderManagerVulkan.h | 19 +++- GPU/Vulkan/VulkanUtil.cpp | 7 +- ext/native/thin3d/thin3d_vulkan.cpp | 4 +- 16 files changed, 365 insertions(+), 41 deletions(-) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index b87bee1065..c14d6a561e 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -937,17 +937,6 @@ void VulkanContext::DestroyDevice() { device_ = nullptr; } -VkPipelineCache VulkanContext::CreatePipelineCache() { - VkPipelineCache cache; - VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; - pc.pInitialData = nullptr; - pc.initialDataSize = 0; - pc.flags = 0; - VkResult res = vkCreatePipelineCache(device_, &pc, nullptr, &cache); - assert(VK_SUCCESS == res); - return cache; -} - bool VulkanContext::CreateShaderModule(const std::vector &spirv, VkShaderModule *shaderModule) { VkShaderModuleCreateInfo sm{ VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO }; sm.pCode = spirv.data(); diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index e452ac38b9..3bb4080694 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -142,8 +142,6 @@ public: VulkanDeleteList &Delete() { return globalDeleteList_; } - VkPipelineCache CreatePipelineCache(); - // The parameters are whatever the chosen window system wants. void InitSurface(WindowSystem winsys, void *data1, void *data2, int width = -1, int height = -1); void ReinitSurface(int width = -1, int height = -1); diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index ae6854a586..140aee1499 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -88,6 +88,8 @@ public: return numDrawCalls; } + VertexDecoder *GetVertexDecoder(u32 vtype); + protected: virtual void ClearTrackedVertexArrays() {} @@ -106,8 +108,6 @@ protected: bool ApplyShaderBlending(); - VertexDecoder *GetVertexDecoder(u32 vtype); - inline int IndexSize(u32 vtype) const { const u32 indexType = (vtype & GE_VTYPE_IDX_MASK); if (indexType == GE_VTYPE_IDX_16BIT) { diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index ebb21a4938..bf0793fe86 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -75,6 +75,21 @@ void DecVtxFormat::ComputeID() { id = uvfmt | (c0fmt << 4) | (c1fmt << 8) | (nrmfmt << 12) | (posfmt << 16); } +void DecVtxFormat::InitializeFromID(uint32_t id) { + this->id = id; + uvfmt = (id & 0xF); + c0fmt = ((id >> 4) & 0xF); + c1fmt = ((id >> 8) & 0xF); + nrmfmt = ((id >> 12) & 0xF); + posfmt = ((id >> 16) & 0xF); + uvoff = 0; + c0off = uvoff + DecFmtSize(uvfmt); + c1off = c0off + DecFmtSize(c0fmt); + nrmoff = c1off + DecFmtSize(c1fmt); + posoff = nrmoff + DecFmtSize(nrmfmt); + stride = posoff + DecFmtSize(posfmt); +} + void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound) { // Find index bounds. Could cache this in display lists. // Also, this could be greatly sped up with SSE2/NEON, although rarely a bottleneck. diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 3c346c1cfb..6acf5c48d8 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -72,10 +72,11 @@ struct DecVtxFormat { u8 c1fmt; u8 c1off; u8 nrmfmt; u8 nrmoff; u8 posfmt; u8 posoff; - short stride; + u8 stride; uint32_t id; void ComputeID(); + void InitializeFromID(uint32_t id); }; void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound); diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 24c84b616a..0dcf21a6ab 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -109,7 +109,7 @@ void DrawEngineGLES::DeviceRestore() { void DrawEngineGLES::InitDeviceObjects() { for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { - frameData_[i].pushVertex = new GLPushBuffer(render_, GL_ARRAY_BUFFER, 1024 * 1024); + frameData_[i].pushVertex = new GLPushBuffer(render_, GL_ARRAY_BUFFER, 256 * 1024); frameData_[i].pushIndex = new GLPushBuffer(render_, GL_ELEMENT_ARRAY_BUFFER, 256 * 1024); render_->RegisterPushBuffer(i, frameData_[i].pushVertex); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 41d03a3304..ca64acae56 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -419,7 +419,7 @@ void GPU_GLES::BeginFrame() { GPUCommon::BeginFrame(); - // Save the cache from time to time. TODO: How often? + // Save the cache from time to time. TODO: How often? We save on exit, so shouldn't need to do this all that often. if (!shaderCachePath_.empty() && (gpuStats.numFlips & 4095) == 0) { shaderManagerGL_->Save(shaderCachePath_); } diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 601c7dc8ca..6fdc1855b7 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -255,9 +255,7 @@ void DrawEngineVulkan::BeginFrame() { // TODO: How can we make this nicer... ((TessellationDataTransferVulkan *)tessDataTransfer)->SetPushBuffer(frame->pushUBO); - // TODO : Find a better place to do this. if (!nullTexture_) { - ILOG("INIT : Creating null texture"); VkCommandBuffer cmdInit = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::INIT_COMMANDBUFFER); nullTexture_ = new VulkanTexture(vulkan_, textureCache_->GetAllocator()); int w = 8; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index f4b1731777..c073f8d95b 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -29,6 +29,7 @@ #include "Core/Config.h" #include "Core/Reporting.h" #include "Core/System.h" +#include "Core/ELF/ParamSFO.h" #include "GPU/GPUState.h" #include "GPU/ge_constants.h" @@ -94,9 +95,57 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) if (vulkan_->GetFeaturesEnabled().wideLines) { drawEngine_.SetLineWidth(PSP_CoreParameter().renderWidth / 480.0f); } + + // Load shader cache. + std::string discID = g_paramSFO.GetDiscID(); + if (discID.size()) { + File::CreateFullPath(GetSysDirectory(DIRECTORY_APP_CACHE)); + shaderCachePath_ = GetSysDirectory(DIRECTORY_APP_CACHE) + "/" + discID + ".vkshadercache"; + + LoadCache(shaderCachePath_); + } +} + +void GPU_Vulkan::LoadCache(std::string filename) { + PSP_SetLoading("Loading shader cache..."); + // Actually precompiled by IsReady() since we're single-threaded. + FILE *f = File::OpenCFile(filename, "rb"); + if (!f) + return; + + // First compile shaders to SPIR-V, then load the pipeline cache and recreate the pipelines. + // It's when recreating the pipelines that the pipeline cache is useful - in the ideal case, + // it can just memcpy the finished shader binaries out of the pipeline cache file. + bool result = shaderManagerVulkan_->LoadCache(f); + if (result) { + VkRenderPass renderPass = g_Config.iRenderingMode == FB_BUFFERED_MODE ? + (VkRenderPass)draw_->GetNativeObject(Draw::NativeObject::FRAMEBUFFER_RENDERPASS) : + (VkRenderPass)draw_->GetNativeObject(Draw::NativeObject::BACKBUFFER_RENDERPASS); + result = pipelineManager_->LoadCache(f, false, shaderManagerVulkan_, &drawEngine_, drawEngine_.GetPipelineLayout(), renderPass); + } + fclose(f); + if (!result) { + WARN_LOG(G3D, "Bad Vulkan pipeline cache"); + // Bad cache file for this GPU/Driver/etc. Delete it. + File::Delete(filename); + } else { + INFO_LOG(G3D, "Loaded Vulkan pipeline cache."); + } +} + +void GPU_Vulkan::SaveCache(std::string filename) { + FILE *f = File::OpenCFile(filename, "wb"); + if (!f) + return; + shaderManagerVulkan_->SaveCache(f); + pipelineManager_->SaveCache(f, false, shaderManagerVulkan_); + INFO_LOG(G3D, "Saved Vulkan pipeline cache"); + fclose(f); } GPU_Vulkan::~GPU_Vulkan() { + SaveCache(shaderCachePath_); + // Note: We save the cache in DeviceLost DestroyDeviceObjects(); framebufferManagerVulkan_->DestroyAllFBOs(); vulkan2D_.Shutdown(); @@ -407,6 +456,9 @@ void GPU_Vulkan::DestroyDeviceObjects() { } void GPU_Vulkan::DeviceLost() { + if (!shaderCachePath_.empty()) { + SaveCache(shaderCachePath_); + } DestroyDeviceObjects(); framebufferManagerVulkan_->DeviceLost(); vulkan2D_.DeviceLost(); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 4357f854db..7e81e6c271 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -80,6 +80,9 @@ private: void InitDeviceObjects(); void DestroyDeviceObjects(); + void LoadCache(std::string filename); + void SaveCache(std::string filename); + VulkanContext *vulkan_; FramebufferManagerVulkan *framebufferManagerVulkan_; TextureCacheVulkan *textureCacheVulkan_; @@ -100,4 +103,6 @@ private: }; FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES]{}; + + std::string shaderCachePath_; }; diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index e44ff9f83d..cfea933c15 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -1,4 +1,5 @@ #include +#include #include "profiler/profiler.h" @@ -8,9 +9,10 @@ #include "GPU/Vulkan/VulkanUtil.h" #include "GPU/Vulkan/PipelineManagerVulkan.h" #include "GPU/Vulkan/ShaderManagerVulkan.h" +#include "GPU/Common/DrawEngineCommon.h" PipelineManagerVulkan::PipelineManagerVulkan(VulkanContext *vulkan) : vulkan_(vulkan), pipelines_(256) { - pipelineCache_ = vulkan->CreatePipelineCache(); + // The pipeline cache is created on demand (or explicitly through Load). } PipelineManagerVulkan::~PipelineManagerVulkan() { @@ -40,7 +42,7 @@ void PipelineManagerVulkan::DeviceLost() { void PipelineManagerVulkan::DeviceRestore(VulkanContext *vulkan) { vulkan_ = vulkan; - pipelineCache_ = vulkan->CreatePipelineCache(); + // The pipeline cache is created on demand. } struct DeclTypeInfo { @@ -97,7 +99,7 @@ static int SetupVertexAttribs(VkVertexInputAttributeDescription attrs[], const D return count; } -static int SetupVertexAttribsPretransformed(VkVertexInputAttributeDescription attrs[], const DecVtxFormat &decFmt) { +static int SetupVertexAttribsPretransformed(VkVertexInputAttributeDescription attrs[]) { int count = 0; VertexAttribSetup(&attrs[count++], DEC_FLOAT_4, 0, PspAttributeLocation::POSITION); VertexAttribSetup(&attrs[count++], DEC_FLOAT_3, 16, PspAttributeLocation::TEXCOORD); @@ -223,7 +225,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip attributeCount = SetupVertexAttribs(attrs, *decFmt); vertexStride = decFmt->stride; } else { - attributeCount = SetupVertexAttribsPretransformed(attrs, *decFmt); + attributeCount = SetupVertexAttribsPretransformed(attrs); vertexStride = 36; } @@ -293,6 +295,12 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip } VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layout, VkRenderPass renderPass, const VulkanPipelineRasterStateKey &rasterKey, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform) { + if (!pipelineCache_) { + VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; + VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_); + assert(VK_SUCCESS == res); + } + VulkanPipelineKey key{}; _assert_msg_(G3D, renderPass, "Can't create a pipeline with a null renderpass"); @@ -301,7 +309,7 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layo key.useHWTransform = useHwTransform; key.vShader = vs->GetModule(); key.fShader = fs->GetModule(); - key.vtxDecId = useHwTransform ? decFmt->id : 0; + key.vtxFmtId = useHwTransform ? decFmt->id : 0; auto iter = pipelines_.Get(key); if (iter) @@ -459,9 +467,9 @@ std::string PipelineManagerVulkan::DebugGetObjectString(std::string id, DebugSha if (pipelineKey.useHWTransform) { str << "HWX "; } - if (pipelineKey.vtxDecId) { + if (pipelineKey.vtxFmtId) { str << "V("; - str << StringFromFormat("%08x", pipelineKey.vtxDecId); // TODO: Format nicer. + str << StringFromFormat("%08x", pipelineKey.vtxFmtId); // TODO: Format nicer. str << ") "; } else { str << "SWX "; @@ -492,3 +500,145 @@ void PipelineManagerVulkan::SetLineWidth(float lineWidth) { } }); } + +// For some reason this struct is only defined in the spec, not in the headers. +struct VkPipelineCacheHeader { + uint32_t headerSize; + VkPipelineCacheHeaderVersion version; + uint32_t vendorId; + uint32_t deviceId; + uint8_t uuid[VK_UUID_SIZE]; +}; + +void PipelineManagerVulkan::SaveCache(FILE *file, bool saveRawPipelineCache, ShaderManagerVulkan *shaderManager) { + size_t dataSize = 0; + uint32_t size; + + if (saveRawPipelineCache) { + VkResult result = vkGetPipelineCacheData(vulkan_->GetDevice(), pipelineCache_, &dataSize, nullptr); + uint32_t size = (uint32_t)dataSize; + if (result != VK_SUCCESS) { + size = 0; + fwrite(&size, sizeof(size), 1, file); + return; + } + std::unique_ptr buffer(new uint8_t[dataSize]); + vkGetPipelineCacheData(vulkan_->GetDevice(), pipelineCache_, &dataSize, buffer.get()); + size = (uint32_t)dataSize; + fwrite(&size, sizeof(size), 1, file); + fwrite(buffer.get(), 1, size, file); + NOTICE_LOG(G3D, "Saved Vulkan pipeline cache (%d bytes).", (int)size); + } + + size_t seekPosOnFailure = ftell(file); + // Write the number of pipelines. + size = (uint32_t)pipelines_.size(); + fwrite(&size, sizeof(size), 1, file); + + bool failed = false; + int count = 0; + pipelines_.Iterate([&](const VulkanPipelineKey &pkey, VulkanPipeline *value) { + if (failed) + return; + VulkanVertexShader *vshader = shaderManager->GetVertexShaderFromModule(pkey.vShader); + VulkanFragmentShader *fshader = shaderManager->GetFragmentShaderFromModule(pkey.fShader); + if (!vshader || !fshader) { + failed = true; + return; + } + StoredVulkanPipelineKey key{}; + key.raster = pkey.raster; + key.useHWTransform = pkey.useHWTransform; + key.fShaderID = fshader->GetID(); + key.vShaderID = vshader->GetID(); + if (key.useHWTransform) { + // NOTE: This is not a vtype, but a decoded vertex format. + key.vtxFmtId = pkey.vtxFmtId; + } + fwrite(&key, sizeof(key), 1, file); + count++; + }); + + if (failed) { + ERROR_LOG(G3D, "Failed to write pipeline cache, some shader was missing"); + // Write a zero in the right place so it doesn't try to load the pipelines next time. + size = 0; + fseek(file, (long)seekPosOnFailure, SEEK_SET); + fwrite(&size, sizeof(size), 1, file); + return; + } + NOTICE_LOG(G3D, "Saved Vulkan pipeline ID cache (%d pipelines).", (int)count); +} + +bool PipelineManagerVulkan::LoadCache(FILE *file, bool loadRawPipelineCache, ShaderManagerVulkan *shaderManager, DrawEngineCommon *drawEngine, VkPipelineLayout layout, VkRenderPass renderPass) { + uint32_t size = 0; + if (loadRawPipelineCache) { + fread(&size, sizeof(size), 1, file); + if (!size) { + WARN_LOG(G3D, "Zero-sized Vulkan pipeline cache."); + return true; + } + std::unique_ptr buffer(new uint8_t[size]); + fread(buffer.get(), 1, size, file); + // Verify header. + VkPipelineCacheHeader *header = (VkPipelineCacheHeader *)buffer.get(); + if (header->version != VK_PIPELINE_CACHE_HEADER_VERSION_ONE) { + // Bad header, don't do anything. + WARN_LOG(G3D, "Bad Vulkan pipeline cache header - ignoring"); + return false; + } + if (0 != memcmp(header->uuid, vulkan_->GetPhysicalDeviceProperties().pipelineCacheUUID, VK_UUID_SIZE)) { + // Wrong hardware/driver/etc. + WARN_LOG(G3D, "Bad Vulkan pipeline cache UUID - ignoring"); + return false; + } + + VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; + pc.pInitialData = buffer.get(); + pc.initialDataSize = size; + pc.flags = 0; + VkPipelineCache cache; + VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &cache); + if (res != VK_SUCCESS) { + return false; + } + if (!pipelineCache_) { + pipelineCache_ = cache; + } else { + vkMergePipelineCaches(vulkan_->GetDevice(), pipelineCache_, 1, &cache); + } + } else { + if (!pipelineCache_) { + VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; + VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_); + } + NOTICE_LOG(G3D, "Loaded Vulkan pipeline cache (%d bytes).", (int)size); + } + + // Read the number of pipelines. + fread(&size, sizeof(size), 1, file); + + NOTICE_LOG(G3D, "Creating %d pipelines...", size); + bool failed = false; + for (uint32_t i = 0; i < size; i++) { + if (failed) { + continue; + } + StoredVulkanPipelineKey key; + fread(&key, sizeof(key), 1, file); + VulkanVertexShader *vs = shaderManager->GetVertexShaderFromID(key.vShaderID); + VulkanFragmentShader *fs = shaderManager->GetFragmentShaderFromID(key.fShaderID); + if (!vs || !fs) { + failed = true; + ERROR_LOG(G3D, "Failed to find vs or fs in of pipeline %d in cache", (int)i); + continue; + } + DecVtxFormat fmt; + fmt.InitializeFromID(key.vtxFmtId); + GetOrCreatePipeline(layout, renderPass, key.raster, + key.useHWTransform ? &fmt : 0, + vs, fs, key.useHWTransform); + } + NOTICE_LOG(G3D, "Recreated Vulkan pipeline cache (%d pipelines).", (int)size); + return true; +} diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index 590cbd9cb5..4494fbc41d 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -42,7 +42,7 @@ struct VulkanPipelineKey { VkRenderPass renderPass; VkShaderModule vShader; VkShaderModule fShader; - uint32_t vtxDecId; + uint32_t vtxFmtId; bool useHWTransform; void ToString(std::string *str) const { @@ -54,6 +54,14 @@ struct VulkanPipelineKey { } }; +struct StoredVulkanPipelineKey { + VulkanPipelineRasterStateKey raster; + VShaderID vShaderID; + FShaderID fShaderID; + uint32_t vtxFmtId; + bool useHWTransform; +}; + enum PipelineFlags { PIPELINE_FLAG_USES_BASE_UB = (1 << 0), PIPELINE_FLAG_USES_LIGHT_UB = (1 << 1), @@ -74,6 +82,8 @@ struct VulkanPipeline { class VulkanContext; class VulkanVertexShader; class VulkanFragmentShader; +class ShaderManagerVulkan; +class DrawEngineCommon; class PipelineManagerVulkan { public: @@ -93,9 +103,13 @@ public: std::string DebugGetObjectString(std::string id, DebugShaderType type, DebugShaderStringType stringType); std::vector DebugGetObjectIDs(DebugShaderType type); + // Saves data for faster creation next time. + void SaveCache(FILE *file, bool saveRawPipelineCache, ShaderManagerVulkan *shaderManager); + bool LoadCache(FILE *file, bool loadRawPipelineCache, ShaderManagerVulkan *shaderManager, DrawEngineCommon *drawEngine, VkPipelineLayout layout, VkRenderPass renderPass); + private: DenseHashMap pipelines_; - VkPipelineCache pipelineCache_; + VkPipelineCache pipelineCache_ = VK_NULL_HANDLE; VulkanContext *vulkan_; float lineWidth_ = 1.0f; }; diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 4131a24047..9b525ec29b 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -40,8 +40,8 @@ #include "GPU/Vulkan/FragmentShaderGeneratorVulkan.h" #include "GPU/Vulkan/VertexShaderGeneratorVulkan.h" -VulkanFragmentShader::VulkanFragmentShader(VulkanContext *vulkan, FShaderID id, const char *code, bool useHWTransform) - : vulkan_(vulkan), id_(id), failed_(false), useHWTransform_(useHWTransform), module_(0) { +VulkanFragmentShader::VulkanFragmentShader(VulkanContext *vulkan, FShaderID id, const char *code) + : vulkan_(vulkan), id_(id), failed_(false), module_(0) { PROFILE_THIS_SCOPE("shadercomp"); source_ = code; @@ -98,7 +98,7 @@ std::string VulkanFragmentShader::GetShaderString(DebugShaderStringType type) co } } -VulkanVertexShader::VulkanVertexShader(VulkanContext *vulkan, VShaderID id, const char *code, int vertType, bool useHWTransform, bool usesLighting) +VulkanVertexShader::VulkanVertexShader(VulkanContext *vulkan, VShaderID id, const char *code, bool useHWTransform, bool usesLighting) : vulkan_(vulkan), id_(id), failed_(false), useHWTransform_(useHWTransform), module_(VK_NULL_HANDLE), usesLighting_(usesLighting) { PROFILE_THIS_SCOPE("shadercomp"); source_ = code; @@ -254,7 +254,7 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader // Vertex shader not in cache. Let's compile it. bool usesLighting; GenerateVulkanGLSLVertexShader(VSID, codeBuffer_, &usesLighting); - vs = new VulkanVertexShader(vulkan_, VSID, codeBuffer_, vertType, useHWTransform, usesLighting); + vs = new VulkanVertexShader(vulkan_, VSID, codeBuffer_, useHWTransform, usesLighting); vsCache_.Insert(VSID, vs); } lastVSID_ = VSID; @@ -263,7 +263,7 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader if (!fs) { // Fragment shader not in cache. Let's compile it. GenerateVulkanGLSLFragmentShader(FSID, codeBuffer_); - fs = new VulkanFragmentShader(vulkan_, FSID, codeBuffer_, useHWTransform); + fs = new VulkanFragmentShader(vulkan_, FSID, codeBuffer_); fsCache_.Insert(FSID, fs); } @@ -323,3 +323,89 @@ std::string ShaderManagerVulkan::DebugGetShaderString(std::string id, DebugShade return "N/A"; } } + +VulkanVertexShader *ShaderManagerVulkan::GetVertexShaderFromModule(VkShaderModule module) { + VulkanVertexShader *vs = nullptr; + vsCache_.Iterate([&](const VShaderID &id, VulkanVertexShader *shader) { + if (shader->GetModule() == module) + vs = shader; + }); + return vs; +} + +VulkanFragmentShader *ShaderManagerVulkan::GetFragmentShaderFromModule(VkShaderModule module) { + VulkanFragmentShader *fs = nullptr; + fsCache_.Iterate([&](const FShaderID &id, VulkanFragmentShader *shader) { + if (shader->GetModule() == module) + fs = shader; + }); + return fs; +} + +// Shader cache. +// +// We simply store the IDs of the shaders used during gameplay. On next startup of +// the same game, we simply compile all the shaders from the start, so we don't have to +// compile them on the fly later. We also store the Vulkan pipeline cache, so if it contains +// pipelines compiled from SPIR-V matching these shaders, pipeline creation will be practically +// instantaneous. + +#define CACHE_HEADER_MAGIC 0xff51f420 +#define CACHE_VERSION 5 +struct VulkanCacheHeader { + uint32_t magic; + uint32_t version; + uint32_t featureFlags; + uint32_t reserved; + int numVertexShaders; + int numFragmentShaders; +}; + +bool ShaderManagerVulkan::LoadCache(FILE *f) { + VulkanCacheHeader header{}; + fread(&header, sizeof(header), 1, f); + if (header.magic != CACHE_HEADER_MAGIC) + return false; + if (header.version != CACHE_VERSION) + return false; + if (header.featureFlags != gstate_c.featureFlags) + return false; + + for (int i = 0; i < header.numVertexShaders; i++) { + VShaderID id; + fread(&id, sizeof(id), 1, f); + bool useHWTransform = id.Bit(VS_BIT_USE_HW_TRANSFORM); + bool usesLighting; + GenerateVulkanGLSLVertexShader(id, codeBuffer_, &usesLighting); + VulkanVertexShader *vs = new VulkanVertexShader(vulkan_, id, codeBuffer_, useHWTransform, usesLighting); + vsCache_.Insert(id, vs); + } + for (int i = 0; i < header.numFragmentShaders; i++) { + FShaderID id; + fread(&id, sizeof(id), 1, f); + GenerateVulkanGLSLFragmentShader(id, codeBuffer_); + VulkanFragmentShader *fs = new VulkanFragmentShader(vulkan_, id, codeBuffer_); + fsCache_.Insert(id, fs); + } + + NOTICE_LOG(G3D, "Loaded %d vertex and %d fragment shaders", header.numVertexShaders, header.numFragmentShaders); + return true; +} + +void ShaderManagerVulkan::SaveCache(FILE *f) { + VulkanCacheHeader header{}; + header.magic = CACHE_HEADER_MAGIC; + header.version = CACHE_VERSION; + header.featureFlags = gstate_c.featureFlags; + header.reserved = 0; + header.numVertexShaders = (int)vsCache_.size(); + header.numFragmentShaders = (int)fsCache_.size(); + fwrite(&header, sizeof(header), 1, f); + vsCache_.Iterate([&](const VShaderID &id, VulkanVertexShader *vs) { + fwrite(&id, sizeof(id), 1, f); + }); + fsCache_.Iterate([&](const FShaderID &id, VulkanFragmentShader *fs) { + fwrite(&id, sizeof(id), 1, f); + }); + NOTICE_LOG(G3D, "Saved %d vertex and %d fragment shaders", header.numVertexShaders, header.numFragmentShaders); +} diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index b8593d5d3a..8e6db9495c 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -17,6 +17,8 @@ #pragma once +#include + #include "base/basictypes.h" #include "Common/Hashmaps.h" #include "Common/Vulkan/VulkanMemory.h" @@ -33,16 +35,16 @@ class VulkanPushBuffer; class VulkanFragmentShader { public: - VulkanFragmentShader(VulkanContext *vulkan, FShaderID id, const char *code, bool useHWTransform); + VulkanFragmentShader(VulkanContext *vulkan, FShaderID id, const char *code); ~VulkanFragmentShader(); const std::string &source() const { return source_; } bool Failed() const { return failed_; } - bool UseHWTransform() const { return useHWTransform_; } std::string GetShaderString(DebugShaderStringType type) const; VkShaderModule GetModule() const { return module_; } + const FShaderID &GetID() { return id_; } protected: VkShaderModule module_; @@ -50,13 +52,12 @@ protected: VulkanContext *vulkan_; std::string source_; bool failed_; - bool useHWTransform_; FShaderID id_; }; class VulkanVertexShader { public: - VulkanVertexShader(VulkanContext *vulkan, VShaderID id, const char *code, int vertType, bool useHWTransform, bool usesLighting); + VulkanVertexShader(VulkanContext *vulkan, VShaderID id, const char *code, bool useHWTransform, bool usesLighting); ~VulkanVertexShader(); const std::string &source() const { return source_; } @@ -69,6 +70,7 @@ public: std::string GetShaderString(DebugShaderStringType type) const; VkShaderModule GetModule() const { return module_; } + const VShaderID &GetID() { return id_; } protected: VkShaderModule module_; @@ -98,6 +100,12 @@ public: int GetNumVertexShaders() const { return (int)vsCache_.size(); } int GetNumFragmentShaders() const { return (int)fsCache_.size(); } + // Used for saving/loading the cache. Don't need to be particularly fast. + VulkanVertexShader *GetVertexShaderFromID(VShaderID id) { return vsCache_.Get(id); } + VulkanFragmentShader *GetFragmentShaderFromID(FShaderID id) { return fsCache_.Get(id); } + VulkanVertexShader *GetVertexShaderFromModule(VkShaderModule module); + VulkanFragmentShader *GetFragmentShaderFromModule(VkShaderModule module); + std::vector DebugGetShaderIDs(DebugShaderType type); std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType); @@ -115,6 +123,9 @@ public: return dest->PushAligned(&ub_lights, sizeof(ub_lights), uboAlignment_, buf); } + bool LoadCache(FILE *f); + void SaveCache(FILE *f); + private: void Clear(); diff --git a/GPU/Vulkan/VulkanUtil.cpp b/GPU/Vulkan/VulkanUtil.cpp index f262c40479..d7d6223fc8 100644 --- a/GPU/Vulkan/VulkanUtil.cpp +++ b/GPU/Vulkan/VulkanUtil.cpp @@ -62,7 +62,10 @@ void Vulkan2D::DestroyDeviceObjects() { } void Vulkan2D::InitDeviceObjects() { - pipelineCache_ = vulkan_->CreatePipelineCache(); + VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; + VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_); + assert(VK_SUCCESS == res); + VkDescriptorSetLayoutBinding bindings[2] = {}; // Texture. bindings[0].descriptorCount = 1; @@ -80,7 +83,7 @@ void Vulkan2D::InitDeviceObjects() { VkDescriptorSetLayoutCreateInfo dsl = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; dsl.bindingCount = 2; dsl.pBindings = bindings; - VkResult res = vkCreateDescriptorSetLayout(device, &dsl, nullptr, &descriptorSetLayout_); + res = vkCreateDescriptorSetLayout(device, &dsl, nullptr, &descriptorSetLayout_); assert(VK_SUCCESS == res); VkDescriptorPoolSize dpTypes[1]; diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 1899512bd3..0eef38ad14 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -773,7 +773,9 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) res = vkCreatePipelineLayout(device_, &pl, nullptr, &pipelineLayout_); assert(VK_SUCCESS == res); - pipelineCache_ = vulkan_->CreatePipelineCache(); + VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; + res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_); + assert(VK_SUCCESS == res); renderManager_.SetSplitSubmit(splitSubmit); From d4a4844bff8cf763af940c2e5a2eff715ec352de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 16 Mar 2018 21:29:16 +0100 Subject: [PATCH 257/291] Update glslang to the latest version --- ext/glslang | 2 +- ext/glslang-build/Android.mk | 1 + ext/glslang.vcxproj | 2 ++ ext/glslang.vcxproj.filters | 6 ++++++ 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ext/glslang b/ext/glslang index 2edde6665d..0af69da12e 160000 --- a/ext/glslang +++ b/ext/glslang @@ -1 +1 @@ -Subproject commit 2edde6665d9a56ead5ea0e55b4e64d9a803e6164 +Subproject commit 0af69da12ede4ce588b7316be55fb095dfe2fb7d diff --git a/ext/glslang-build/Android.mk b/ext/glslang-build/Android.mk index 8bf8106ca0..47e232c5cf 100644 --- a/ext/glslang-build/Android.mk +++ b/ext/glslang-build/Android.mk @@ -9,6 +9,7 @@ LOCAL_ARM_MODE := arm LOCAL_SRC_FILES := \ ../glslang/glslang/GenericCodeGen/CodeGen.cpp \ ../glslang/glslang/GenericCodeGen/Link.cpp \ + ../glslang/glslang/MachineIndependent/attribute.cpp \ ../glslang/glslang/MachineIndependent/Constant.cpp \ ../glslang/glslang/MachineIndependent/glslang_tab.cpp \ ../glslang/glslang/MachineIndependent/InfoSink.cpp \ diff --git a/ext/glslang.vcxproj b/ext/glslang.vcxproj index 54b3581255..3711148daa 100644 --- a/ext/glslang.vcxproj +++ b/ext/glslang.vcxproj @@ -152,6 +152,7 @@ + @@ -207,6 +208,7 @@ + diff --git a/ext/glslang.vcxproj.filters b/ext/glslang.vcxproj.filters index af94d50565..d37c8c805e 100644 --- a/ext/glslang.vcxproj.filters +++ b/ext/glslang.vcxproj.filters @@ -137,6 +137,9 @@ HLSL + + glslang + @@ -290,6 +293,9 @@ HLSL + + glslang + From 6858c7761276fe615af59b7c4b7a6f7631576085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Mar 2018 01:53:19 +0100 Subject: [PATCH 258/291] Don't allow wrapping on framebuffer textures. Fixes GTA on old NV Shield --- GPU/GLES/DrawEngineGLES.cpp | 2 +- GPU/GLES/ShaderManagerGLES.cpp | 2 -- GPU/GLES/ShaderManagerGLES.h | 6 ++---- UI/DevScreens.cpp | 3 ++- ext/native/thin3d/GLQueueRunner.cpp | 18 +++++++++++------- ext/native/thin3d/GLRenderManager.h | 5 +++-- 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 0dcf21a6ab..24c84b616a 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -109,7 +109,7 @@ void DrawEngineGLES::DeviceRestore() { void DrawEngineGLES::InitDeviceObjects() { for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { - frameData_[i].pushVertex = new GLPushBuffer(render_, GL_ARRAY_BUFFER, 256 * 1024); + frameData_[i].pushVertex = new GLPushBuffer(render_, GL_ARRAY_BUFFER, 1024 * 1024); frameData_[i].pushIndex = new GLPushBuffer(render_, GL_ELEMENT_ARRAY_BUFFER, 256 * 1024); render_->RegisterPushBuffer(i, frameData_[i].pushVertex); diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 399b01c1b0..237e1edb56 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -79,8 +79,6 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, semantics.push_back({ ATTR_POSITION, "position" }); semantics.push_back({ ATTR_TEXCOORD, "texcoord" }); semantics.push_back({ ATTR_NORMAL, "normal" }); - semantics.push_back({ ATTR_W1, "w1" }); - semantics.push_back({ ATTR_W2, "w2" }); semantics.push_back({ ATTR_COLOR0, "color0" }); semantics.push_back({ ATTR_COLOR1, "color1" }); diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index 7f19a77e28..6c6efd5b3a 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -34,10 +34,8 @@ enum { ATTR_POSITION = 0, ATTR_TEXCOORD = 1, ATTR_NORMAL = 2, - ATTR_W1 = 3, - ATTR_W2 = 4, - ATTR_COLOR0 = 5, - ATTR_COLOR1 = 6, + ATTR_COLOR0 = 3, + ATTR_COLOR1 = 4, ATTR_COUNT, }; diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index c499a90392..227265233b 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -120,7 +120,8 @@ UI::EventReturn DevMenu::OnJitCompare(UI::EventParams &e) { UI::EventReturn DevMenu::OnShaderView(UI::EventParams &e) { UpdateUIState(UISTATE_PAUSEMENU); - screenManager()->push(new ShaderListScreen()); + if (gpu) // Avoid crashing if chosen while the game is being loaded. + screenManager()->push(new ShaderListScreen()); return UI::EVENT_DONE; } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 46850f3c70..f183dbe8c5 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -326,10 +326,12 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) { fbo->color_texture.wrapT = GL_CLAMP_TO_EDGE; fbo->color_texture.magFilter = GL_LINEAR; fbo->color_texture.minFilter = GL_LINEAR; + fbo->color_texture.canWrap = false; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, fbo->color_texture.wrapS); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, fbo->color_texture.wrapT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, fbo->color_texture.magFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, fbo->color_texture.minFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); if (gl_extensions.IsGLES) { if (gl_extensions.OES_packed_depth_stencil) { @@ -846,13 +848,15 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { if (!tex) { break; } - if (tex->wrapS != c.textureSampler.wrapS) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS); - tex->wrapS = c.textureSampler.wrapS; - } - if (tex->wrapT != c.textureSampler.wrapT) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT); - tex->wrapT = c.textureSampler.wrapT; + if (tex->canWrap) { + if (tex->wrapS != c.textureSampler.wrapS) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS); + tex->wrapS = c.textureSampler.wrapS; + } + if (tex->wrapT != c.textureSampler.wrapT) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT); + tex->wrapT = c.textureSampler.wrapT; + } } if (tex->magFilter != c.textureSampler.magFilter) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter); diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 5cb4e54e61..e697aa3220 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -33,9 +33,10 @@ public: GLenum wrapT = 0xFFFF; GLenum magFilter = 0xFFFF; GLenum minFilter = 0xFFFF; + bool canWrap = true; float anisotropy = -100000.0f; - float minLod = -100000.0f; - float maxLod = 100000.0f; + float minLod = -1000.0f; + float maxLod = 1000.0f; float lodBias = 0.0f; }; From 9761d8930d76e01157b646a8687beb389768564a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Mar 2018 02:01:11 +0100 Subject: [PATCH 259/291] Bump GL shader cache version --- GPU/GLES/ShaderManagerGLES.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 237e1edb56..a585cbd174 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -788,7 +788,7 @@ std::string ShaderManagerGLES::DebugGetShaderString(std::string id, DebugShaderT // as sometimes these features might have an effect on the ID bits. #define CACHE_HEADER_MAGIC 0x83277592 -#define CACHE_VERSION 6 +#define CACHE_VERSION 7 struct CacheHeader { uint32_t magic; uint32_t version; From 71630b81cfbd874dc3f70cd750eb4325b4281b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Mar 2018 09:24:19 +0100 Subject: [PATCH 260/291] Update Vulkan headers to 1.1. Might as well keep up. --- ext/vulkan/icd-spv.h | 34 - ext/vulkan/spirv.h | 49 +- ext/vulkan/spirv.hpp | 1993 +++---- ext/vulkan/spirv.hpp11 | 1993 +++---- ext/vulkan/spirv.json | 2025 +++---- ext/vulkan/spirv.lua | 1887 +++---- ext/vulkan/spirv.py | 1887 +++---- ext/vulkan/vk_icd.h | 10 +- ext/vulkan/vk_layer.h | 63 +- ext/vulkan/vk_layer_dispatch_table.h | 198 +- ext/vulkan/vk_platform.h | 28 - ext/vulkan/vk_sdk_platform.h | 25 +- ext/vulkan/vulkan.h | 6841 +----------------------- ext/vulkan/vulkan_android.h | 60 + ext/vulkan/vulkan_core.h | 7334 ++++++++++++++++++++++++++ ext/vulkan/vulkan_ios.h | 58 + ext/vulkan/vulkan_macos.h | 58 + ext/vulkan/vulkan_mir.h | 65 + ext/vulkan/vulkan_vi.h | 58 + ext/vulkan/vulkan_wayland.h | 65 + ext/vulkan/vulkan_win32.h | 276 + ext/vulkan/vulkan_xcb.h | 66 + ext/vulkan/vulkan_xlib.h | 66 + ext/vulkan/vulkan_xlib_xrandr.h | 54 + 24 files changed, 13487 insertions(+), 11706 deletions(-) delete mode 100644 ext/vulkan/icd-spv.h create mode 100644 ext/vulkan/vulkan_android.h create mode 100644 ext/vulkan/vulkan_core.h create mode 100644 ext/vulkan/vulkan_ios.h create mode 100644 ext/vulkan/vulkan_macos.h create mode 100644 ext/vulkan/vulkan_mir.h create mode 100644 ext/vulkan/vulkan_vi.h create mode 100644 ext/vulkan/vulkan_wayland.h create mode 100644 ext/vulkan/vulkan_win32.h create mode 100644 ext/vulkan/vulkan_xcb.h create mode 100644 ext/vulkan/vulkan_xlib.h create mode 100644 ext/vulkan/vulkan_xlib_xrandr.h diff --git a/ext/vulkan/icd-spv.h b/ext/vulkan/icd-spv.h deleted file mode 100644 index cc65284a19..0000000000 --- a/ext/vulkan/icd-spv.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2015-2016 Valve Corporation - * Copyright (c) 2015-2016 LunarG, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Author: Cody Northrop - */ - -#ifndef ICD_SPV_H -#define ICD_SPV_H - -#include - -#define ICD_SPV_MAGIC 0x07230203 -#define ICD_SPV_VERSION 99 - -struct icd_spv_header { - uint32_t magic; - uint32_t version; - uint32_t gen_magic; // Generator's magic number -}; - -#endif /* ICD_SPV_H */ diff --git a/ext/vulkan/spirv.h b/ext/vulkan/spirv.h index 89354c0696..2be35146df 100644 --- a/ext/vulkan/spirv.h +++ b/ext/vulkan/spirv.h @@ -51,11 +51,11 @@ typedef unsigned int SpvId; #define SPV_VERSION 0x10100 -#define SPV_REVISION 6 +#define SPV_REVISION 8 static const unsigned int SpvMagicNumber = 0x07230203; static const unsigned int SpvVersion = 0x00010100; -static const unsigned int SpvRevision = 6; +static const unsigned int SpvRevision = 8; static const unsigned int SpvOpCodeMask = 0xffff; static const unsigned int SpvWordCountShift = 16; @@ -65,6 +65,7 @@ typedef enum SpvSourceLanguage_ { SpvSourceLanguageGLSL = 2, SpvSourceLanguageOpenCL_C = 3, SpvSourceLanguageOpenCL_CPP = 4, + SpvSourceLanguageHLSL = 5, SpvSourceLanguageMax = 0x7fffffff, } SpvSourceLanguage; @@ -129,6 +130,8 @@ typedef enum SpvExecutionMode_ { SpvExecutionModeFinalizer = 34, SpvExecutionModeSubgroupSize = 35, SpvExecutionModeSubgroupsPerWorkgroup = 36, + SpvExecutionModePostDepthCoverage = 4446, + SpvExecutionModeStencilRefReplacingEXT = 5027, SpvExecutionModeMax = 0x7fffffff, } SpvExecutionMode; @@ -145,6 +148,7 @@ typedef enum SpvStorageClass_ { SpvStorageClassPushConstant = 9, SpvStorageClassAtomicCounter = 10, SpvStorageClassImage = 11, + SpvStorageClassStorageBuffer = 12, SpvStorageClassMax = 0x7fffffff, } SpvStorageClass; @@ -383,6 +387,7 @@ typedef enum SpvDecoration_ { SpvDecorationInputAttachmentIndex = 43, SpvDecorationAlignment = 44, SpvDecorationMaxByteOffset = 45, + SpvDecorationExplicitInterpAMD = 4999, SpvDecorationOverrideCoverageNV = 5248, SpvDecorationPassthroughNV = 5250, SpvDecorationViewportRelativeNV = 5252, @@ -442,6 +447,14 @@ typedef enum SpvBuiltIn_ { SpvBuiltInDrawIndex = 4426, SpvBuiltInDeviceIndex = 4438, SpvBuiltInViewIndex = 4440, + SpvBuiltInBaryCoordNoPerspAMD = 4992, + SpvBuiltInBaryCoordNoPerspCentroidAMD = 4993, + SpvBuiltInBaryCoordNoPerspSampleAMD = 4994, + SpvBuiltInBaryCoordSmoothAMD = 4995, + SpvBuiltInBaryCoordSmoothCentroidAMD = 4996, + SpvBuiltInBaryCoordSmoothSampleAMD = 4997, + SpvBuiltInBaryCoordPullModelAMD = 4998, + SpvBuiltInFragStencilRefEXT = 5014, SpvBuiltInViewportMaskNV = 5253, SpvBuiltInSecondaryPositionNV = 5257, SpvBuiltInSecondaryViewportMaskNV = 5258, @@ -632,18 +645,32 @@ typedef enum SpvCapability_ { SpvCapabilitySubgroupBallotKHR = 4423, SpvCapabilityDrawParameters = 4427, SpvCapabilitySubgroupVoteKHR = 4431, + SpvCapabilityStorageBuffer16BitAccess = 4433, SpvCapabilityStorageUniformBufferBlock16 = 4433, SpvCapabilityStorageUniform16 = 4434, + SpvCapabilityUniformAndStorageBuffer16BitAccess = 4434, SpvCapabilityStoragePushConstant16 = 4435, SpvCapabilityStorageInputOutput16 = 4436, SpvCapabilityDeviceGroup = 4437, SpvCapabilityMultiView = 4439, + SpvCapabilityVariablePointersStorageBuffer = 4441, + SpvCapabilityVariablePointers = 4442, + SpvCapabilityAtomicStorageOps = 4445, + SpvCapabilitySampleMaskPostDepthCoverage = 4447, + SpvCapabilityImageGatherBiasLodAMD = 5009, + SpvCapabilityFragmentMaskAMD = 5010, + SpvCapabilityStencilExportEXT = 5013, + SpvCapabilityImageReadWriteLodAMD = 5015, SpvCapabilitySampleMaskOverrideCoverageNV = 5249, SpvCapabilityGeometryShaderPassthroughNV = 5251, + SpvCapabilityShaderViewportIndexLayerEXT = 5254, SpvCapabilityShaderViewportIndexLayerNV = 5254, SpvCapabilityShaderViewportMaskNV = 5255, SpvCapabilityShaderStereoViewNV = 5259, SpvCapabilityPerViewAttributesNV = 5260, + SpvCapabilitySubgroupShuffleINTEL = 5568, + SpvCapabilitySubgroupBufferBlockIOINTEL = 5569, + SpvCapabilitySubgroupImageBlockIOINTEL = 5570, SpvCapabilityMax = 0x7fffffff, } SpvCapability; @@ -958,6 +985,24 @@ typedef enum SpvOp_ { SpvOpSubgroupAnyKHR = 4429, SpvOpSubgroupAllEqualKHR = 4430, SpvOpSubgroupReadInvocationKHR = 4432, + SpvOpGroupIAddNonUniformAMD = 5000, + SpvOpGroupFAddNonUniformAMD = 5001, + SpvOpGroupFMinNonUniformAMD = 5002, + SpvOpGroupUMinNonUniformAMD = 5003, + SpvOpGroupSMinNonUniformAMD = 5004, + SpvOpGroupFMaxNonUniformAMD = 5005, + SpvOpGroupUMaxNonUniformAMD = 5006, + SpvOpGroupSMaxNonUniformAMD = 5007, + SpvOpFragmentMaskFetchAMD = 5011, + SpvOpFragmentFetchAMD = 5012, + SpvOpSubgroupShuffleINTEL = 5571, + SpvOpSubgroupShuffleDownINTEL = 5572, + SpvOpSubgroupShuffleUpINTEL = 5573, + SpvOpSubgroupShuffleXorINTEL = 5574, + SpvOpSubgroupBlockReadINTEL = 5575, + SpvOpSubgroupBlockWriteINTEL = 5576, + SpvOpSubgroupImageBlockReadINTEL = 5577, + SpvOpSubgroupImageBlockWriteINTEL = 5578, SpvOpMax = 0x7fffffff, } SpvOp; diff --git a/ext/vulkan/spirv.hpp b/ext/vulkan/spirv.hpp index 1bac2c0277..b9ae21ecef 100644 --- a/ext/vulkan/spirv.hpp +++ b/ext/vulkan/spirv.hpp @@ -1,974 +1,1019 @@ -// Copyright (c) 2014-2017 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and/or associated documentation files (the "Materials"), -// to deal in the Materials without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Materials, and to permit persons to whom the -// Materials are furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Materials. -// -// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -// IN THE MATERIALS. - -// This header is automatically generated by the same tool that creates -// the Binary Section of the SPIR-V specification. - -// Enumeration tokens for SPIR-V, in various styles: -// C, C++, C++11, JSON, Lua, Python -// -// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL -// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL -// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL -// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL -// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] -// -// Some tokens act like mask values, which can be OR'd together, -// while others are mutually exclusive. The mask-like ones have -// "Mask" in their name, and a parallel enum that has the shift -// amount (1 << x) for each corresponding enumerant. - -#ifndef spirv_HPP -#define spirv_HPP - -namespace spv { - -typedef unsigned int Id; - -#define SPV_VERSION 0x10100 -#define SPV_REVISION 6 - -static const unsigned int MagicNumber = 0x07230203; -static const unsigned int Version = 0x00010100; -static const unsigned int Revision = 6; -static const unsigned int OpCodeMask = 0xffff; -static const unsigned int WordCountShift = 16; - -enum SourceLanguage { - SourceLanguageUnknown = 0, - SourceLanguageESSL = 1, - SourceLanguageGLSL = 2, - SourceLanguageOpenCL_C = 3, - SourceLanguageOpenCL_CPP = 4, - SourceLanguageMax = 0x7fffffff, -}; - -enum ExecutionModel { - ExecutionModelVertex = 0, - ExecutionModelTessellationControl = 1, - ExecutionModelTessellationEvaluation = 2, - ExecutionModelGeometry = 3, - ExecutionModelFragment = 4, - ExecutionModelGLCompute = 5, - ExecutionModelKernel = 6, - ExecutionModelMax = 0x7fffffff, -}; - -enum AddressingModel { - AddressingModelLogical = 0, - AddressingModelPhysical32 = 1, - AddressingModelPhysical64 = 2, - AddressingModelMax = 0x7fffffff, -}; - -enum MemoryModel { - MemoryModelSimple = 0, - MemoryModelGLSL450 = 1, - MemoryModelOpenCL = 2, - MemoryModelMax = 0x7fffffff, -}; - -enum ExecutionMode { - ExecutionModeInvocations = 0, - ExecutionModeSpacingEqual = 1, - ExecutionModeSpacingFractionalEven = 2, - ExecutionModeSpacingFractionalOdd = 3, - ExecutionModeVertexOrderCw = 4, - ExecutionModeVertexOrderCcw = 5, - ExecutionModePixelCenterInteger = 6, - ExecutionModeOriginUpperLeft = 7, - ExecutionModeOriginLowerLeft = 8, - ExecutionModeEarlyFragmentTests = 9, - ExecutionModePointMode = 10, - ExecutionModeXfb = 11, - ExecutionModeDepthReplacing = 12, - ExecutionModeDepthGreater = 14, - ExecutionModeDepthLess = 15, - ExecutionModeDepthUnchanged = 16, - ExecutionModeLocalSize = 17, - ExecutionModeLocalSizeHint = 18, - ExecutionModeInputPoints = 19, - ExecutionModeInputLines = 20, - ExecutionModeInputLinesAdjacency = 21, - ExecutionModeTriangles = 22, - ExecutionModeInputTrianglesAdjacency = 23, - ExecutionModeQuads = 24, - ExecutionModeIsolines = 25, - ExecutionModeOutputVertices = 26, - ExecutionModeOutputPoints = 27, - ExecutionModeOutputLineStrip = 28, - ExecutionModeOutputTriangleStrip = 29, - ExecutionModeVecTypeHint = 30, - ExecutionModeContractionOff = 31, - ExecutionModeInitializer = 33, - ExecutionModeFinalizer = 34, - ExecutionModeSubgroupSize = 35, - ExecutionModeSubgroupsPerWorkgroup = 36, - ExecutionModeMax = 0x7fffffff, -}; - -enum StorageClass { - StorageClassUniformConstant = 0, - StorageClassInput = 1, - StorageClassUniform = 2, - StorageClassOutput = 3, - StorageClassWorkgroup = 4, - StorageClassCrossWorkgroup = 5, - StorageClassPrivate = 6, - StorageClassFunction = 7, - StorageClassGeneric = 8, - StorageClassPushConstant = 9, - StorageClassAtomicCounter = 10, - StorageClassImage = 11, - StorageClassMax = 0x7fffffff, -}; - -enum Dim { - Dim1D = 0, - Dim2D = 1, - Dim3D = 2, - DimCube = 3, - DimRect = 4, - DimBuffer = 5, - DimSubpassData = 6, - DimMax = 0x7fffffff, -}; - -enum SamplerAddressingMode { - SamplerAddressingModeNone = 0, - SamplerAddressingModeClampToEdge = 1, - SamplerAddressingModeClamp = 2, - SamplerAddressingModeRepeat = 3, - SamplerAddressingModeRepeatMirrored = 4, - SamplerAddressingModeMax = 0x7fffffff, -}; - -enum SamplerFilterMode { - SamplerFilterModeNearest = 0, - SamplerFilterModeLinear = 1, - SamplerFilterModeMax = 0x7fffffff, -}; - -enum ImageFormat { - ImageFormatUnknown = 0, - ImageFormatRgba32f = 1, - ImageFormatRgba16f = 2, - ImageFormatR32f = 3, - ImageFormatRgba8 = 4, - ImageFormatRgba8Snorm = 5, - ImageFormatRg32f = 6, - ImageFormatRg16f = 7, - ImageFormatR11fG11fB10f = 8, - ImageFormatR16f = 9, - ImageFormatRgba16 = 10, - ImageFormatRgb10A2 = 11, - ImageFormatRg16 = 12, - ImageFormatRg8 = 13, - ImageFormatR16 = 14, - ImageFormatR8 = 15, - ImageFormatRgba16Snorm = 16, - ImageFormatRg16Snorm = 17, - ImageFormatRg8Snorm = 18, - ImageFormatR16Snorm = 19, - ImageFormatR8Snorm = 20, - ImageFormatRgba32i = 21, - ImageFormatRgba16i = 22, - ImageFormatRgba8i = 23, - ImageFormatR32i = 24, - ImageFormatRg32i = 25, - ImageFormatRg16i = 26, - ImageFormatRg8i = 27, - ImageFormatR16i = 28, - ImageFormatR8i = 29, - ImageFormatRgba32ui = 30, - ImageFormatRgba16ui = 31, - ImageFormatRgba8ui = 32, - ImageFormatR32ui = 33, - ImageFormatRgb10a2ui = 34, - ImageFormatRg32ui = 35, - ImageFormatRg16ui = 36, - ImageFormatRg8ui = 37, - ImageFormatR16ui = 38, - ImageFormatR8ui = 39, - ImageFormatMax = 0x7fffffff, -}; - -enum ImageChannelOrder { - ImageChannelOrderR = 0, - ImageChannelOrderA = 1, - ImageChannelOrderRG = 2, - ImageChannelOrderRA = 3, - ImageChannelOrderRGB = 4, - ImageChannelOrderRGBA = 5, - ImageChannelOrderBGRA = 6, - ImageChannelOrderARGB = 7, - ImageChannelOrderIntensity = 8, - ImageChannelOrderLuminance = 9, - ImageChannelOrderRx = 10, - ImageChannelOrderRGx = 11, - ImageChannelOrderRGBx = 12, - ImageChannelOrderDepth = 13, - ImageChannelOrderDepthStencil = 14, - ImageChannelOrdersRGB = 15, - ImageChannelOrdersRGBx = 16, - ImageChannelOrdersRGBA = 17, - ImageChannelOrdersBGRA = 18, - ImageChannelOrderABGR = 19, - ImageChannelOrderMax = 0x7fffffff, -}; - -enum ImageChannelDataType { - ImageChannelDataTypeSnormInt8 = 0, - ImageChannelDataTypeSnormInt16 = 1, - ImageChannelDataTypeUnormInt8 = 2, - ImageChannelDataTypeUnormInt16 = 3, - ImageChannelDataTypeUnormShort565 = 4, - ImageChannelDataTypeUnormShort555 = 5, - ImageChannelDataTypeUnormInt101010 = 6, - ImageChannelDataTypeSignedInt8 = 7, - ImageChannelDataTypeSignedInt16 = 8, - ImageChannelDataTypeSignedInt32 = 9, - ImageChannelDataTypeUnsignedInt8 = 10, - ImageChannelDataTypeUnsignedInt16 = 11, - ImageChannelDataTypeUnsignedInt32 = 12, - ImageChannelDataTypeHalfFloat = 13, - ImageChannelDataTypeFloat = 14, - ImageChannelDataTypeUnormInt24 = 15, - ImageChannelDataTypeUnormInt101010_2 = 16, - ImageChannelDataTypeMax = 0x7fffffff, -}; - -enum ImageOperandsShift { - ImageOperandsBiasShift = 0, - ImageOperandsLodShift = 1, - ImageOperandsGradShift = 2, - ImageOperandsConstOffsetShift = 3, - ImageOperandsOffsetShift = 4, - ImageOperandsConstOffsetsShift = 5, - ImageOperandsSampleShift = 6, - ImageOperandsMinLodShift = 7, - ImageOperandsMax = 0x7fffffff, -}; - -enum ImageOperandsMask { - ImageOperandsMaskNone = 0, - ImageOperandsBiasMask = 0x00000001, - ImageOperandsLodMask = 0x00000002, - ImageOperandsGradMask = 0x00000004, - ImageOperandsConstOffsetMask = 0x00000008, - ImageOperandsOffsetMask = 0x00000010, - ImageOperandsConstOffsetsMask = 0x00000020, - ImageOperandsSampleMask = 0x00000040, - ImageOperandsMinLodMask = 0x00000080, -}; - -enum FPFastMathModeShift { - FPFastMathModeNotNaNShift = 0, - FPFastMathModeNotInfShift = 1, - FPFastMathModeNSZShift = 2, - FPFastMathModeAllowRecipShift = 3, - FPFastMathModeFastShift = 4, - FPFastMathModeMax = 0x7fffffff, -}; - -enum FPFastMathModeMask { - FPFastMathModeMaskNone = 0, - FPFastMathModeNotNaNMask = 0x00000001, - FPFastMathModeNotInfMask = 0x00000002, - FPFastMathModeNSZMask = 0x00000004, - FPFastMathModeAllowRecipMask = 0x00000008, - FPFastMathModeFastMask = 0x00000010, -}; - -enum FPRoundingMode { - FPRoundingModeRTE = 0, - FPRoundingModeRTZ = 1, - FPRoundingModeRTP = 2, - FPRoundingModeRTN = 3, - FPRoundingModeMax = 0x7fffffff, -}; - -enum LinkageType { - LinkageTypeExport = 0, - LinkageTypeImport = 1, - LinkageTypeMax = 0x7fffffff, -}; - -enum AccessQualifier { - AccessQualifierReadOnly = 0, - AccessQualifierWriteOnly = 1, - AccessQualifierReadWrite = 2, - AccessQualifierMax = 0x7fffffff, -}; - -enum FunctionParameterAttribute { - FunctionParameterAttributeZext = 0, - FunctionParameterAttributeSext = 1, - FunctionParameterAttributeByVal = 2, - FunctionParameterAttributeSret = 3, - FunctionParameterAttributeNoAlias = 4, - FunctionParameterAttributeNoCapture = 5, - FunctionParameterAttributeNoWrite = 6, - FunctionParameterAttributeNoReadWrite = 7, - FunctionParameterAttributeMax = 0x7fffffff, -}; - -enum Decoration { - DecorationRelaxedPrecision = 0, - DecorationSpecId = 1, - DecorationBlock = 2, - DecorationBufferBlock = 3, - DecorationRowMajor = 4, - DecorationColMajor = 5, - DecorationArrayStride = 6, - DecorationMatrixStride = 7, - DecorationGLSLShared = 8, - DecorationGLSLPacked = 9, - DecorationCPacked = 10, - DecorationBuiltIn = 11, - DecorationNoPerspective = 13, - DecorationFlat = 14, - DecorationPatch = 15, - DecorationCentroid = 16, - DecorationSample = 17, - DecorationInvariant = 18, - DecorationRestrict = 19, - DecorationAliased = 20, - DecorationVolatile = 21, - DecorationConstant = 22, - DecorationCoherent = 23, - DecorationNonWritable = 24, - DecorationNonReadable = 25, - DecorationUniform = 26, - DecorationSaturatedConversion = 28, - DecorationStream = 29, - DecorationLocation = 30, - DecorationComponent = 31, - DecorationIndex = 32, - DecorationBinding = 33, - DecorationDescriptorSet = 34, - DecorationOffset = 35, - DecorationXfbBuffer = 36, - DecorationXfbStride = 37, - DecorationFuncParamAttr = 38, - DecorationFPRoundingMode = 39, - DecorationFPFastMathMode = 40, - DecorationLinkageAttributes = 41, - DecorationNoContraction = 42, - DecorationInputAttachmentIndex = 43, - DecorationAlignment = 44, - DecorationMaxByteOffset = 45, - DecorationOverrideCoverageNV = 5248, - DecorationPassthroughNV = 5250, - DecorationViewportRelativeNV = 5252, - DecorationSecondaryViewportRelativeNV = 5256, - DecorationMax = 0x7fffffff, -}; - -enum BuiltIn { - BuiltInPosition = 0, - BuiltInPointSize = 1, - BuiltInClipDistance = 3, - BuiltInCullDistance = 4, - BuiltInVertexId = 5, - BuiltInInstanceId = 6, - BuiltInPrimitiveId = 7, - BuiltInInvocationId = 8, - BuiltInLayer = 9, - BuiltInViewportIndex = 10, - BuiltInTessLevelOuter = 11, - BuiltInTessLevelInner = 12, - BuiltInTessCoord = 13, - BuiltInPatchVertices = 14, - BuiltInFragCoord = 15, - BuiltInPointCoord = 16, - BuiltInFrontFacing = 17, - BuiltInSampleId = 18, - BuiltInSamplePosition = 19, - BuiltInSampleMask = 20, - BuiltInFragDepth = 22, - BuiltInHelperInvocation = 23, - BuiltInNumWorkgroups = 24, - BuiltInWorkgroupSize = 25, - BuiltInWorkgroupId = 26, - BuiltInLocalInvocationId = 27, - BuiltInGlobalInvocationId = 28, - BuiltInLocalInvocationIndex = 29, - BuiltInWorkDim = 30, - BuiltInGlobalSize = 31, - BuiltInEnqueuedWorkgroupSize = 32, - BuiltInGlobalOffset = 33, - BuiltInGlobalLinearId = 34, - BuiltInSubgroupSize = 36, - BuiltInSubgroupMaxSize = 37, - BuiltInNumSubgroups = 38, - BuiltInNumEnqueuedSubgroups = 39, - BuiltInSubgroupId = 40, - BuiltInSubgroupLocalInvocationId = 41, - BuiltInVertexIndex = 42, - BuiltInInstanceIndex = 43, - BuiltInSubgroupEqMaskKHR = 4416, - BuiltInSubgroupGeMaskKHR = 4417, - BuiltInSubgroupGtMaskKHR = 4418, - BuiltInSubgroupLeMaskKHR = 4419, - BuiltInSubgroupLtMaskKHR = 4420, - BuiltInBaseVertex = 4424, - BuiltInBaseInstance = 4425, - BuiltInDrawIndex = 4426, - BuiltInDeviceIndex = 4438, - BuiltInViewIndex = 4440, - BuiltInViewportMaskNV = 5253, - BuiltInSecondaryPositionNV = 5257, - BuiltInSecondaryViewportMaskNV = 5258, - BuiltInPositionPerViewNV = 5261, - BuiltInViewportMaskPerViewNV = 5262, - BuiltInMax = 0x7fffffff, -}; - -enum SelectionControlShift { - SelectionControlFlattenShift = 0, - SelectionControlDontFlattenShift = 1, - SelectionControlMax = 0x7fffffff, -}; - -enum SelectionControlMask { - SelectionControlMaskNone = 0, - SelectionControlFlattenMask = 0x00000001, - SelectionControlDontFlattenMask = 0x00000002, -}; - -enum LoopControlShift { - LoopControlUnrollShift = 0, - LoopControlDontUnrollShift = 1, - LoopControlDependencyInfiniteShift = 2, - LoopControlDependencyLengthShift = 3, - LoopControlMax = 0x7fffffff, -}; - -enum LoopControlMask { - LoopControlMaskNone = 0, - LoopControlUnrollMask = 0x00000001, - LoopControlDontUnrollMask = 0x00000002, - LoopControlDependencyInfiniteMask = 0x00000004, - LoopControlDependencyLengthMask = 0x00000008, -}; - -enum FunctionControlShift { - FunctionControlInlineShift = 0, - FunctionControlDontInlineShift = 1, - FunctionControlPureShift = 2, - FunctionControlConstShift = 3, - FunctionControlMax = 0x7fffffff, -}; - -enum FunctionControlMask { - FunctionControlMaskNone = 0, - FunctionControlInlineMask = 0x00000001, - FunctionControlDontInlineMask = 0x00000002, - FunctionControlPureMask = 0x00000004, - FunctionControlConstMask = 0x00000008, -}; - -enum MemorySemanticsShift { - MemorySemanticsAcquireShift = 1, - MemorySemanticsReleaseShift = 2, - MemorySemanticsAcquireReleaseShift = 3, - MemorySemanticsSequentiallyConsistentShift = 4, - MemorySemanticsUniformMemoryShift = 6, - MemorySemanticsSubgroupMemoryShift = 7, - MemorySemanticsWorkgroupMemoryShift = 8, - MemorySemanticsCrossWorkgroupMemoryShift = 9, - MemorySemanticsAtomicCounterMemoryShift = 10, - MemorySemanticsImageMemoryShift = 11, - MemorySemanticsMax = 0x7fffffff, -}; - -enum MemorySemanticsMask { - MemorySemanticsMaskNone = 0, - MemorySemanticsAcquireMask = 0x00000002, - MemorySemanticsReleaseMask = 0x00000004, - MemorySemanticsAcquireReleaseMask = 0x00000008, - MemorySemanticsSequentiallyConsistentMask = 0x00000010, - MemorySemanticsUniformMemoryMask = 0x00000040, - MemorySemanticsSubgroupMemoryMask = 0x00000080, - MemorySemanticsWorkgroupMemoryMask = 0x00000100, - MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, - MemorySemanticsAtomicCounterMemoryMask = 0x00000400, - MemorySemanticsImageMemoryMask = 0x00000800, -}; - -enum MemoryAccessShift { - MemoryAccessVolatileShift = 0, - MemoryAccessAlignedShift = 1, - MemoryAccessNontemporalShift = 2, - MemoryAccessMax = 0x7fffffff, -}; - -enum MemoryAccessMask { - MemoryAccessMaskNone = 0, - MemoryAccessVolatileMask = 0x00000001, - MemoryAccessAlignedMask = 0x00000002, - MemoryAccessNontemporalMask = 0x00000004, -}; - -enum Scope { - ScopeCrossDevice = 0, - ScopeDevice = 1, - ScopeWorkgroup = 2, - ScopeSubgroup = 3, - ScopeInvocation = 4, - ScopeMax = 0x7fffffff, -}; - -enum GroupOperation { - GroupOperationReduce = 0, - GroupOperationInclusiveScan = 1, - GroupOperationExclusiveScan = 2, - GroupOperationMax = 0x7fffffff, -}; - -enum KernelEnqueueFlags { - KernelEnqueueFlagsNoWait = 0, - KernelEnqueueFlagsWaitKernel = 1, - KernelEnqueueFlagsWaitWorkGroup = 2, - KernelEnqueueFlagsMax = 0x7fffffff, -}; - -enum KernelProfilingInfoShift { - KernelProfilingInfoCmdExecTimeShift = 0, - KernelProfilingInfoMax = 0x7fffffff, -}; - -enum KernelProfilingInfoMask { - KernelProfilingInfoMaskNone = 0, - KernelProfilingInfoCmdExecTimeMask = 0x00000001, -}; - -enum Capability { - CapabilityMatrix = 0, - CapabilityShader = 1, - CapabilityGeometry = 2, - CapabilityTessellation = 3, - CapabilityAddresses = 4, - CapabilityLinkage = 5, - CapabilityKernel = 6, - CapabilityVector16 = 7, - CapabilityFloat16Buffer = 8, - CapabilityFloat16 = 9, - CapabilityFloat64 = 10, - CapabilityInt64 = 11, - CapabilityInt64Atomics = 12, - CapabilityImageBasic = 13, - CapabilityImageReadWrite = 14, - CapabilityImageMipmap = 15, - CapabilityPipes = 17, - CapabilityGroups = 18, - CapabilityDeviceEnqueue = 19, - CapabilityLiteralSampler = 20, - CapabilityAtomicStorage = 21, - CapabilityInt16 = 22, - CapabilityTessellationPointSize = 23, - CapabilityGeometryPointSize = 24, - CapabilityImageGatherExtended = 25, - CapabilityStorageImageMultisample = 27, - CapabilityUniformBufferArrayDynamicIndexing = 28, - CapabilitySampledImageArrayDynamicIndexing = 29, - CapabilityStorageBufferArrayDynamicIndexing = 30, - CapabilityStorageImageArrayDynamicIndexing = 31, - CapabilityClipDistance = 32, - CapabilityCullDistance = 33, - CapabilityImageCubeArray = 34, - CapabilitySampleRateShading = 35, - CapabilityImageRect = 36, - CapabilitySampledRect = 37, - CapabilityGenericPointer = 38, - CapabilityInt8 = 39, - CapabilityInputAttachment = 40, - CapabilitySparseResidency = 41, - CapabilityMinLod = 42, - CapabilitySampled1D = 43, - CapabilityImage1D = 44, - CapabilitySampledCubeArray = 45, - CapabilitySampledBuffer = 46, - CapabilityImageBuffer = 47, - CapabilityImageMSArray = 48, - CapabilityStorageImageExtendedFormats = 49, - CapabilityImageQuery = 50, - CapabilityDerivativeControl = 51, - CapabilityInterpolationFunction = 52, - CapabilityTransformFeedback = 53, - CapabilityGeometryStreams = 54, - CapabilityStorageImageReadWithoutFormat = 55, - CapabilityStorageImageWriteWithoutFormat = 56, - CapabilityMultiViewport = 57, - CapabilitySubgroupDispatch = 58, - CapabilityNamedBarrier = 59, - CapabilityPipeStorage = 60, - CapabilitySubgroupBallotKHR = 4423, - CapabilityDrawParameters = 4427, - CapabilitySubgroupVoteKHR = 4431, - CapabilityStorageUniformBufferBlock16 = 4433, - CapabilityStorageUniform16 = 4434, - CapabilityStoragePushConstant16 = 4435, - CapabilityStorageInputOutput16 = 4436, - CapabilityDeviceGroup = 4437, - CapabilityMultiView = 4439, - CapabilitySampleMaskOverrideCoverageNV = 5249, - CapabilityGeometryShaderPassthroughNV = 5251, - CapabilityShaderViewportIndexLayerNV = 5254, - CapabilityShaderViewportMaskNV = 5255, - CapabilityShaderStereoViewNV = 5259, - CapabilityPerViewAttributesNV = 5260, - CapabilityMax = 0x7fffffff, -}; - -enum Op { - OpNop = 0, - OpUndef = 1, - OpSourceContinued = 2, - OpSource = 3, - OpSourceExtension = 4, - OpName = 5, - OpMemberName = 6, - OpString = 7, - OpLine = 8, - OpExtension = 10, - OpExtInstImport = 11, - OpExtInst = 12, - OpMemoryModel = 14, - OpEntryPoint = 15, - OpExecutionMode = 16, - OpCapability = 17, - OpTypeVoid = 19, - OpTypeBool = 20, - OpTypeInt = 21, - OpTypeFloat = 22, - OpTypeVector = 23, - OpTypeMatrix = 24, - OpTypeImage = 25, - OpTypeSampler = 26, - OpTypeSampledImage = 27, - OpTypeArray = 28, - OpTypeRuntimeArray = 29, - OpTypeStruct = 30, - OpTypeOpaque = 31, - OpTypePointer = 32, - OpTypeFunction = 33, - OpTypeEvent = 34, - OpTypeDeviceEvent = 35, - OpTypeReserveId = 36, - OpTypeQueue = 37, - OpTypePipe = 38, - OpTypeForwardPointer = 39, - OpConstantTrue = 41, - OpConstantFalse = 42, - OpConstant = 43, - OpConstantComposite = 44, - OpConstantSampler = 45, - OpConstantNull = 46, - OpSpecConstantTrue = 48, - OpSpecConstantFalse = 49, - OpSpecConstant = 50, - OpSpecConstantComposite = 51, - OpSpecConstantOp = 52, - OpFunction = 54, - OpFunctionParameter = 55, - OpFunctionEnd = 56, - OpFunctionCall = 57, - OpVariable = 59, - OpImageTexelPointer = 60, - OpLoad = 61, - OpStore = 62, - OpCopyMemory = 63, - OpCopyMemorySized = 64, - OpAccessChain = 65, - OpInBoundsAccessChain = 66, - OpPtrAccessChain = 67, - OpArrayLength = 68, - OpGenericPtrMemSemantics = 69, - OpInBoundsPtrAccessChain = 70, - OpDecorate = 71, - OpMemberDecorate = 72, - OpDecorationGroup = 73, - OpGroupDecorate = 74, - OpGroupMemberDecorate = 75, - OpVectorExtractDynamic = 77, - OpVectorInsertDynamic = 78, - OpVectorShuffle = 79, - OpCompositeConstruct = 80, - OpCompositeExtract = 81, - OpCompositeInsert = 82, - OpCopyObject = 83, - OpTranspose = 84, - OpSampledImage = 86, - OpImageSampleImplicitLod = 87, - OpImageSampleExplicitLod = 88, - OpImageSampleDrefImplicitLod = 89, - OpImageSampleDrefExplicitLod = 90, - OpImageSampleProjImplicitLod = 91, - OpImageSampleProjExplicitLod = 92, - OpImageSampleProjDrefImplicitLod = 93, - OpImageSampleProjDrefExplicitLod = 94, - OpImageFetch = 95, - OpImageGather = 96, - OpImageDrefGather = 97, - OpImageRead = 98, - OpImageWrite = 99, - OpImage = 100, - OpImageQueryFormat = 101, - OpImageQueryOrder = 102, - OpImageQuerySizeLod = 103, - OpImageQuerySize = 104, - OpImageQueryLod = 105, - OpImageQueryLevels = 106, - OpImageQuerySamples = 107, - OpConvertFToU = 109, - OpConvertFToS = 110, - OpConvertSToF = 111, - OpConvertUToF = 112, - OpUConvert = 113, - OpSConvert = 114, - OpFConvert = 115, - OpQuantizeToF16 = 116, - OpConvertPtrToU = 117, - OpSatConvertSToU = 118, - OpSatConvertUToS = 119, - OpConvertUToPtr = 120, - OpPtrCastToGeneric = 121, - OpGenericCastToPtr = 122, - OpGenericCastToPtrExplicit = 123, - OpBitcast = 124, - OpSNegate = 126, - OpFNegate = 127, - OpIAdd = 128, - OpFAdd = 129, - OpISub = 130, - OpFSub = 131, - OpIMul = 132, - OpFMul = 133, - OpUDiv = 134, - OpSDiv = 135, - OpFDiv = 136, - OpUMod = 137, - OpSRem = 138, - OpSMod = 139, - OpFRem = 140, - OpFMod = 141, - OpVectorTimesScalar = 142, - OpMatrixTimesScalar = 143, - OpVectorTimesMatrix = 144, - OpMatrixTimesVector = 145, - OpMatrixTimesMatrix = 146, - OpOuterProduct = 147, - OpDot = 148, - OpIAddCarry = 149, - OpISubBorrow = 150, - OpUMulExtended = 151, - OpSMulExtended = 152, - OpAny = 154, - OpAll = 155, - OpIsNan = 156, - OpIsInf = 157, - OpIsFinite = 158, - OpIsNormal = 159, - OpSignBitSet = 160, - OpLessOrGreater = 161, - OpOrdered = 162, - OpUnordered = 163, - OpLogicalEqual = 164, - OpLogicalNotEqual = 165, - OpLogicalOr = 166, - OpLogicalAnd = 167, - OpLogicalNot = 168, - OpSelect = 169, - OpIEqual = 170, - OpINotEqual = 171, - OpUGreaterThan = 172, - OpSGreaterThan = 173, - OpUGreaterThanEqual = 174, - OpSGreaterThanEqual = 175, - OpULessThan = 176, - OpSLessThan = 177, - OpULessThanEqual = 178, - OpSLessThanEqual = 179, - OpFOrdEqual = 180, - OpFUnordEqual = 181, - OpFOrdNotEqual = 182, - OpFUnordNotEqual = 183, - OpFOrdLessThan = 184, - OpFUnordLessThan = 185, - OpFOrdGreaterThan = 186, - OpFUnordGreaterThan = 187, - OpFOrdLessThanEqual = 188, - OpFUnordLessThanEqual = 189, - OpFOrdGreaterThanEqual = 190, - OpFUnordGreaterThanEqual = 191, - OpShiftRightLogical = 194, - OpShiftRightArithmetic = 195, - OpShiftLeftLogical = 196, - OpBitwiseOr = 197, - OpBitwiseXor = 198, - OpBitwiseAnd = 199, - OpNot = 200, - OpBitFieldInsert = 201, - OpBitFieldSExtract = 202, - OpBitFieldUExtract = 203, - OpBitReverse = 204, - OpBitCount = 205, - OpDPdx = 207, - OpDPdy = 208, - OpFwidth = 209, - OpDPdxFine = 210, - OpDPdyFine = 211, - OpFwidthFine = 212, - OpDPdxCoarse = 213, - OpDPdyCoarse = 214, - OpFwidthCoarse = 215, - OpEmitVertex = 218, - OpEndPrimitive = 219, - OpEmitStreamVertex = 220, - OpEndStreamPrimitive = 221, - OpControlBarrier = 224, - OpMemoryBarrier = 225, - OpAtomicLoad = 227, - OpAtomicStore = 228, - OpAtomicExchange = 229, - OpAtomicCompareExchange = 230, - OpAtomicCompareExchangeWeak = 231, - OpAtomicIIncrement = 232, - OpAtomicIDecrement = 233, - OpAtomicIAdd = 234, - OpAtomicISub = 235, - OpAtomicSMin = 236, - OpAtomicUMin = 237, - OpAtomicSMax = 238, - OpAtomicUMax = 239, - OpAtomicAnd = 240, - OpAtomicOr = 241, - OpAtomicXor = 242, - OpPhi = 245, - OpLoopMerge = 246, - OpSelectionMerge = 247, - OpLabel = 248, - OpBranch = 249, - OpBranchConditional = 250, - OpSwitch = 251, - OpKill = 252, - OpReturn = 253, - OpReturnValue = 254, - OpUnreachable = 255, - OpLifetimeStart = 256, - OpLifetimeStop = 257, - OpGroupAsyncCopy = 259, - OpGroupWaitEvents = 260, - OpGroupAll = 261, - OpGroupAny = 262, - OpGroupBroadcast = 263, - OpGroupIAdd = 264, - OpGroupFAdd = 265, - OpGroupFMin = 266, - OpGroupUMin = 267, - OpGroupSMin = 268, - OpGroupFMax = 269, - OpGroupUMax = 270, - OpGroupSMax = 271, - OpReadPipe = 274, - OpWritePipe = 275, - OpReservedReadPipe = 276, - OpReservedWritePipe = 277, - OpReserveReadPipePackets = 278, - OpReserveWritePipePackets = 279, - OpCommitReadPipe = 280, - OpCommitWritePipe = 281, - OpIsValidReserveId = 282, - OpGetNumPipePackets = 283, - OpGetMaxPipePackets = 284, - OpGroupReserveReadPipePackets = 285, - OpGroupReserveWritePipePackets = 286, - OpGroupCommitReadPipe = 287, - OpGroupCommitWritePipe = 288, - OpEnqueueMarker = 291, - OpEnqueueKernel = 292, - OpGetKernelNDrangeSubGroupCount = 293, - OpGetKernelNDrangeMaxSubGroupSize = 294, - OpGetKernelWorkGroupSize = 295, - OpGetKernelPreferredWorkGroupSizeMultiple = 296, - OpRetainEvent = 297, - OpReleaseEvent = 298, - OpCreateUserEvent = 299, - OpIsValidEvent = 300, - OpSetUserEventStatus = 301, - OpCaptureEventProfilingInfo = 302, - OpGetDefaultQueue = 303, - OpBuildNDRange = 304, - OpImageSparseSampleImplicitLod = 305, - OpImageSparseSampleExplicitLod = 306, - OpImageSparseSampleDrefImplicitLod = 307, - OpImageSparseSampleDrefExplicitLod = 308, - OpImageSparseSampleProjImplicitLod = 309, - OpImageSparseSampleProjExplicitLod = 310, - OpImageSparseSampleProjDrefImplicitLod = 311, - OpImageSparseSampleProjDrefExplicitLod = 312, - OpImageSparseFetch = 313, - OpImageSparseGather = 314, - OpImageSparseDrefGather = 315, - OpImageSparseTexelsResident = 316, - OpNoLine = 317, - OpAtomicFlagTestAndSet = 318, - OpAtomicFlagClear = 319, - OpImageSparseRead = 320, - OpSizeOf = 321, - OpTypePipeStorage = 322, - OpConstantPipeStorage = 323, - OpCreatePipeFromPipeStorage = 324, - OpGetKernelLocalSizeForSubgroupCount = 325, - OpGetKernelMaxNumSubgroups = 326, - OpTypeNamedBarrier = 327, - OpNamedBarrierInitialize = 328, - OpMemoryNamedBarrier = 329, - OpModuleProcessed = 330, - OpSubgroupBallotKHR = 4421, - OpSubgroupFirstInvocationKHR = 4422, - OpSubgroupAllKHR = 4428, - OpSubgroupAnyKHR = 4429, - OpSubgroupAllEqualKHR = 4430, - OpSubgroupReadInvocationKHR = 4432, - OpMax = 0x7fffffff, -}; - -// Overload operator| for mask bit combining - -inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } -inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } -inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } -inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } -inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } -inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } -inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } -inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } - -} // end namespace spv - -#endif // #ifndef spirv_HPP - +// Copyright (c) 2014-2017 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +// This header is automatically generated by the same tool that creates +// the Binary Section of the SPIR-V specification. + +// Enumeration tokens for SPIR-V, in various styles: +// C, C++, C++11, JSON, Lua, Python +// +// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +// +// Some tokens act like mask values, which can be OR'd together, +// while others are mutually exclusive. The mask-like ones have +// "Mask" in their name, and a parallel enum that has the shift +// amount (1 << x) for each corresponding enumerant. + +#ifndef spirv_HPP +#define spirv_HPP + +namespace spv { + +typedef unsigned int Id; + +#define SPV_VERSION 0x10100 +#define SPV_REVISION 8 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010100; +static const unsigned int Revision = 8; +static const unsigned int OpCodeMask = 0xffff; +static const unsigned int WordCountShift = 16; + +enum SourceLanguage { + SourceLanguageUnknown = 0, + SourceLanguageESSL = 1, + SourceLanguageGLSL = 2, + SourceLanguageOpenCL_C = 3, + SourceLanguageOpenCL_CPP = 4, + SourceLanguageHLSL = 5, + SourceLanguageMax = 0x7fffffff, +}; + +enum ExecutionModel { + ExecutionModelVertex = 0, + ExecutionModelTessellationControl = 1, + ExecutionModelTessellationEvaluation = 2, + ExecutionModelGeometry = 3, + ExecutionModelFragment = 4, + ExecutionModelGLCompute = 5, + ExecutionModelKernel = 6, + ExecutionModelMax = 0x7fffffff, +}; + +enum AddressingModel { + AddressingModelLogical = 0, + AddressingModelPhysical32 = 1, + AddressingModelPhysical64 = 2, + AddressingModelMax = 0x7fffffff, +}; + +enum MemoryModel { + MemoryModelSimple = 0, + MemoryModelGLSL450 = 1, + MemoryModelOpenCL = 2, + MemoryModelMax = 0x7fffffff, +}; + +enum ExecutionMode { + ExecutionModeInvocations = 0, + ExecutionModeSpacingEqual = 1, + ExecutionModeSpacingFractionalEven = 2, + ExecutionModeSpacingFractionalOdd = 3, + ExecutionModeVertexOrderCw = 4, + ExecutionModeVertexOrderCcw = 5, + ExecutionModePixelCenterInteger = 6, + ExecutionModeOriginUpperLeft = 7, + ExecutionModeOriginLowerLeft = 8, + ExecutionModeEarlyFragmentTests = 9, + ExecutionModePointMode = 10, + ExecutionModeXfb = 11, + ExecutionModeDepthReplacing = 12, + ExecutionModeDepthGreater = 14, + ExecutionModeDepthLess = 15, + ExecutionModeDepthUnchanged = 16, + ExecutionModeLocalSize = 17, + ExecutionModeLocalSizeHint = 18, + ExecutionModeInputPoints = 19, + ExecutionModeInputLines = 20, + ExecutionModeInputLinesAdjacency = 21, + ExecutionModeTriangles = 22, + ExecutionModeInputTrianglesAdjacency = 23, + ExecutionModeQuads = 24, + ExecutionModeIsolines = 25, + ExecutionModeOutputVertices = 26, + ExecutionModeOutputPoints = 27, + ExecutionModeOutputLineStrip = 28, + ExecutionModeOutputTriangleStrip = 29, + ExecutionModeVecTypeHint = 30, + ExecutionModeContractionOff = 31, + ExecutionModeInitializer = 33, + ExecutionModeFinalizer = 34, + ExecutionModeSubgroupSize = 35, + ExecutionModeSubgroupsPerWorkgroup = 36, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeMax = 0x7fffffff, +}; + +enum StorageClass { + StorageClassUniformConstant = 0, + StorageClassInput = 1, + StorageClassUniform = 2, + StorageClassOutput = 3, + StorageClassWorkgroup = 4, + StorageClassCrossWorkgroup = 5, + StorageClassPrivate = 6, + StorageClassFunction = 7, + StorageClassGeneric = 8, + StorageClassPushConstant = 9, + StorageClassAtomicCounter = 10, + StorageClassImage = 11, + StorageClassStorageBuffer = 12, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + DimMax = 0x7fffffff, +}; + +enum SamplerAddressingMode { + SamplerAddressingModeNone = 0, + SamplerAddressingModeClampToEdge = 1, + SamplerAddressingModeClamp = 2, + SamplerAddressingModeRepeat = 3, + SamplerAddressingModeRepeatMirrored = 4, + SamplerAddressingModeMax = 0x7fffffff, +}; + +enum SamplerFilterMode { + SamplerFilterModeNearest = 0, + SamplerFilterModeLinear = 1, + SamplerFilterModeMax = 0x7fffffff, +}; + +enum ImageFormat { + ImageFormatUnknown = 0, + ImageFormatRgba32f = 1, + ImageFormatRgba16f = 2, + ImageFormatR32f = 3, + ImageFormatRgba8 = 4, + ImageFormatRgba8Snorm = 5, + ImageFormatRg32f = 6, + ImageFormatRg16f = 7, + ImageFormatR11fG11fB10f = 8, + ImageFormatR16f = 9, + ImageFormatRgba16 = 10, + ImageFormatRgb10A2 = 11, + ImageFormatRg16 = 12, + ImageFormatRg8 = 13, + ImageFormatR16 = 14, + ImageFormatR8 = 15, + ImageFormatRgba16Snorm = 16, + ImageFormatRg16Snorm = 17, + ImageFormatRg8Snorm = 18, + ImageFormatR16Snorm = 19, + ImageFormatR8Snorm = 20, + ImageFormatRgba32i = 21, + ImageFormatRgba16i = 22, + ImageFormatRgba8i = 23, + ImageFormatR32i = 24, + ImageFormatRg32i = 25, + ImageFormatRg16i = 26, + ImageFormatRg8i = 27, + ImageFormatR16i = 28, + ImageFormatR8i = 29, + ImageFormatRgba32ui = 30, + ImageFormatRgba16ui = 31, + ImageFormatRgba8ui = 32, + ImageFormatR32ui = 33, + ImageFormatRgb10a2ui = 34, + ImageFormatRg32ui = 35, + ImageFormatRg16ui = 36, + ImageFormatRg8ui = 37, + ImageFormatR16ui = 38, + ImageFormatR8ui = 39, + ImageFormatMax = 0x7fffffff, +}; + +enum ImageChannelOrder { + ImageChannelOrderR = 0, + ImageChannelOrderA = 1, + ImageChannelOrderRG = 2, + ImageChannelOrderRA = 3, + ImageChannelOrderRGB = 4, + ImageChannelOrderRGBA = 5, + ImageChannelOrderBGRA = 6, + ImageChannelOrderARGB = 7, + ImageChannelOrderIntensity = 8, + ImageChannelOrderLuminance = 9, + ImageChannelOrderRx = 10, + ImageChannelOrderRGx = 11, + ImageChannelOrderRGBx = 12, + ImageChannelOrderDepth = 13, + ImageChannelOrderDepthStencil = 14, + ImageChannelOrdersRGB = 15, + ImageChannelOrdersRGBx = 16, + ImageChannelOrdersRGBA = 17, + ImageChannelOrdersBGRA = 18, + ImageChannelOrderABGR = 19, + ImageChannelOrderMax = 0x7fffffff, +}; + +enum ImageChannelDataType { + ImageChannelDataTypeSnormInt8 = 0, + ImageChannelDataTypeSnormInt16 = 1, + ImageChannelDataTypeUnormInt8 = 2, + ImageChannelDataTypeUnormInt16 = 3, + ImageChannelDataTypeUnormShort565 = 4, + ImageChannelDataTypeUnormShort555 = 5, + ImageChannelDataTypeUnormInt101010 = 6, + ImageChannelDataTypeSignedInt8 = 7, + ImageChannelDataTypeSignedInt16 = 8, + ImageChannelDataTypeSignedInt32 = 9, + ImageChannelDataTypeUnsignedInt8 = 10, + ImageChannelDataTypeUnsignedInt16 = 11, + ImageChannelDataTypeUnsignedInt32 = 12, + ImageChannelDataTypeHalfFloat = 13, + ImageChannelDataTypeFloat = 14, + ImageChannelDataTypeUnormInt24 = 15, + ImageChannelDataTypeUnormInt101010_2 = 16, + ImageChannelDataTypeMax = 0x7fffffff, +}; + +enum ImageOperandsShift { + ImageOperandsBiasShift = 0, + ImageOperandsLodShift = 1, + ImageOperandsGradShift = 2, + ImageOperandsConstOffsetShift = 3, + ImageOperandsOffsetShift = 4, + ImageOperandsConstOffsetsShift = 5, + ImageOperandsSampleShift = 6, + ImageOperandsMinLodShift = 7, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + ImageOperandsMaskNone = 0, + ImageOperandsBiasMask = 0x00000001, + ImageOperandsLodMask = 0x00000002, + ImageOperandsGradMask = 0x00000004, + ImageOperandsConstOffsetMask = 0x00000008, + ImageOperandsOffsetMask = 0x00000010, + ImageOperandsConstOffsetsMask = 0x00000020, + ImageOperandsSampleMask = 0x00000040, + ImageOperandsMinLodMask = 0x00000080, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + LinkageTypeMax = 0x7fffffff, +}; + +enum AccessQualifier { + AccessQualifierReadOnly = 0, + AccessQualifierWriteOnly = 1, + AccessQualifierReadWrite = 2, + AccessQualifierMax = 0x7fffffff, +}; + +enum FunctionParameterAttribute { + FunctionParameterAttributeZext = 0, + FunctionParameterAttributeSext = 1, + FunctionParameterAttributeByVal = 2, + FunctionParameterAttributeSret = 3, + FunctionParameterAttributeNoAlias = 4, + FunctionParameterAttributeNoCapture = 5, + FunctionParameterAttributeNoWrite = 6, + FunctionParameterAttributeNoReadWrite = 7, + FunctionParameterAttributeMax = 0x7fffffff, +}; + +enum Decoration { + DecorationRelaxedPrecision = 0, + DecorationSpecId = 1, + DecorationBlock = 2, + DecorationBufferBlock = 3, + DecorationRowMajor = 4, + DecorationColMajor = 5, + DecorationArrayStride = 6, + DecorationMatrixStride = 7, + DecorationGLSLShared = 8, + DecorationGLSLPacked = 9, + DecorationCPacked = 10, + DecorationBuiltIn = 11, + DecorationNoPerspective = 13, + DecorationFlat = 14, + DecorationPatch = 15, + DecorationCentroid = 16, + DecorationSample = 17, + DecorationInvariant = 18, + DecorationRestrict = 19, + DecorationAliased = 20, + DecorationVolatile = 21, + DecorationConstant = 22, + DecorationCoherent = 23, + DecorationNonWritable = 24, + DecorationNonReadable = 25, + DecorationUniform = 26, + DecorationSaturatedConversion = 28, + DecorationStream = 29, + DecorationLocation = 30, + DecorationComponent = 31, + DecorationIndex = 32, + DecorationBinding = 33, + DecorationDescriptorSet = 34, + DecorationOffset = 35, + DecorationXfbBuffer = 36, + DecorationXfbStride = 37, + DecorationFuncParamAttr = 38, + DecorationFPRoundingMode = 39, + DecorationFPFastMathMode = 40, + DecorationLinkageAttributes = 41, + DecorationNoContraction = 42, + DecorationInputAttachmentIndex = 43, + DecorationAlignment = 44, + DecorationMaxByteOffset = 45, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationMax = 0x7fffffff, +}; + +enum BuiltIn { + BuiltInPosition = 0, + BuiltInPointSize = 1, + BuiltInClipDistance = 3, + BuiltInCullDistance = 4, + BuiltInVertexId = 5, + BuiltInInstanceId = 6, + BuiltInPrimitiveId = 7, + BuiltInInvocationId = 8, + BuiltInLayer = 9, + BuiltInViewportIndex = 10, + BuiltInTessLevelOuter = 11, + BuiltInTessLevelInner = 12, + BuiltInTessCoord = 13, + BuiltInPatchVertices = 14, + BuiltInFragCoord = 15, + BuiltInPointCoord = 16, + BuiltInFrontFacing = 17, + BuiltInSampleId = 18, + BuiltInSamplePosition = 19, + BuiltInSampleMask = 20, + BuiltInFragDepth = 22, + BuiltInHelperInvocation = 23, + BuiltInNumWorkgroups = 24, + BuiltInWorkgroupSize = 25, + BuiltInWorkgroupId = 26, + BuiltInLocalInvocationId = 27, + BuiltInGlobalInvocationId = 28, + BuiltInLocalInvocationIndex = 29, + BuiltInWorkDim = 30, + BuiltInGlobalSize = 31, + BuiltInEnqueuedWorkgroupSize = 32, + BuiltInGlobalOffset = 33, + BuiltInGlobalLinearId = 34, + BuiltInSubgroupSize = 36, + BuiltInSubgroupMaxSize = 37, + BuiltInNumSubgroups = 38, + BuiltInNumEnqueuedSubgroups = 39, + BuiltInSubgroupId = 40, + BuiltInSubgroupLocalInvocationId = 41, + BuiltInVertexIndex = 42, + BuiltInInstanceIndex = 43, + BuiltInSubgroupEqMaskKHR = 4416, + BuiltInSubgroupGeMaskKHR = 4417, + BuiltInSubgroupGtMaskKHR = 4418, + BuiltInSubgroupLeMaskKHR = 4419, + BuiltInSubgroupLtMaskKHR = 4420, + BuiltInBaseVertex = 4424, + BuiltInBaseInstance = 4425, + BuiltInDrawIndex = 4426, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + BuiltInViewportMaskNV = 5253, + BuiltInSecondaryPositionNV = 5257, + BuiltInSecondaryViewportMaskNV = 5258, + BuiltInPositionPerViewNV = 5261, + BuiltInViewportMaskPerViewNV = 5262, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + SelectionControlMaskNone = 0, + SelectionControlFlattenMask = 0x00000001, + SelectionControlDontFlattenMask = 0x00000002, +}; + +enum LoopControlShift { + LoopControlUnrollShift = 0, + LoopControlDontUnrollShift = 1, + LoopControlDependencyInfiniteShift = 2, + LoopControlDependencyLengthShift = 3, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +enum MemorySemanticsShift { + MemorySemanticsAcquireShift = 1, + MemorySemanticsReleaseShift = 2, + MemorySemanticsAcquireReleaseShift = 3, + MemorySemanticsSequentiallyConsistentShift = 4, + MemorySemanticsUniformMemoryShift = 6, + MemorySemanticsSubgroupMemoryShift = 7, + MemorySemanticsWorkgroupMemoryShift = 8, + MemorySemanticsCrossWorkgroupMemoryShift = 9, + MemorySemanticsAtomicCounterMemoryShift = 10, + MemorySemanticsImageMemoryShift = 11, + MemorySemanticsMax = 0x7fffffff, +}; + +enum MemorySemanticsMask { + MemorySemanticsMaskNone = 0, + MemorySemanticsAcquireMask = 0x00000002, + MemorySemanticsReleaseMask = 0x00000004, + MemorySemanticsAcquireReleaseMask = 0x00000008, + MemorySemanticsSequentiallyConsistentMask = 0x00000010, + MemorySemanticsUniformMemoryMask = 0x00000040, + MemorySemanticsSubgroupMemoryMask = 0x00000080, + MemorySemanticsWorkgroupMemoryMask = 0x00000100, + MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + MemorySemanticsAtomicCounterMemoryMask = 0x00000400, + MemorySemanticsImageMemoryMask = 0x00000800, +}; + +enum MemoryAccessShift { + MemoryAccessVolatileShift = 0, + MemoryAccessAlignedShift = 1, + MemoryAccessNontemporalShift = 2, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, +}; + +enum Scope { + ScopeCrossDevice = 0, + ScopeDevice = 1, + ScopeWorkgroup = 2, + ScopeSubgroup = 3, + ScopeInvocation = 4, + ScopeMax = 0x7fffffff, +}; + +enum GroupOperation { + GroupOperationReduce = 0, + GroupOperationInclusiveScan = 1, + GroupOperationExclusiveScan = 2, + GroupOperationMax = 0x7fffffff, +}; + +enum KernelEnqueueFlags { + KernelEnqueueFlagsNoWait = 0, + KernelEnqueueFlagsWaitKernel = 1, + KernelEnqueueFlagsWaitWorkGroup = 2, + KernelEnqueueFlagsMax = 0x7fffffff, +}; + +enum KernelProfilingInfoShift { + KernelProfilingInfoCmdExecTimeShift = 0, + KernelProfilingInfoMax = 0x7fffffff, +}; + +enum KernelProfilingInfoMask { + KernelProfilingInfoMaskNone = 0, + KernelProfilingInfoCmdExecTimeMask = 0x00000001, +}; + +enum Capability { + CapabilityMatrix = 0, + CapabilityShader = 1, + CapabilityGeometry = 2, + CapabilityTessellation = 3, + CapabilityAddresses = 4, + CapabilityLinkage = 5, + CapabilityKernel = 6, + CapabilityVector16 = 7, + CapabilityFloat16Buffer = 8, + CapabilityFloat16 = 9, + CapabilityFloat64 = 10, + CapabilityInt64 = 11, + CapabilityInt64Atomics = 12, + CapabilityImageBasic = 13, + CapabilityImageReadWrite = 14, + CapabilityImageMipmap = 15, + CapabilityPipes = 17, + CapabilityGroups = 18, + CapabilityDeviceEnqueue = 19, + CapabilityLiteralSampler = 20, + CapabilityAtomicStorage = 21, + CapabilityInt16 = 22, + CapabilityTessellationPointSize = 23, + CapabilityGeometryPointSize = 24, + CapabilityImageGatherExtended = 25, + CapabilityStorageImageMultisample = 27, + CapabilityUniformBufferArrayDynamicIndexing = 28, + CapabilitySampledImageArrayDynamicIndexing = 29, + CapabilityStorageBufferArrayDynamicIndexing = 30, + CapabilityStorageImageArrayDynamicIndexing = 31, + CapabilityClipDistance = 32, + CapabilityCullDistance = 33, + CapabilityImageCubeArray = 34, + CapabilitySampleRateShading = 35, + CapabilityImageRect = 36, + CapabilitySampledRect = 37, + CapabilityGenericPointer = 38, + CapabilityInt8 = 39, + CapabilityInputAttachment = 40, + CapabilitySparseResidency = 41, + CapabilityMinLod = 42, + CapabilitySampled1D = 43, + CapabilityImage1D = 44, + CapabilitySampledCubeArray = 45, + CapabilitySampledBuffer = 46, + CapabilityImageBuffer = 47, + CapabilityImageMSArray = 48, + CapabilityStorageImageExtendedFormats = 49, + CapabilityImageQuery = 50, + CapabilityDerivativeControl = 51, + CapabilityInterpolationFunction = 52, + CapabilityTransformFeedback = 53, + CapabilityGeometryStreams = 54, + CapabilityStorageImageReadWithoutFormat = 55, + CapabilityStorageImageWriteWithoutFormat = 56, + CapabilityMultiViewport = 57, + CapabilitySubgroupDispatch = 58, + CapabilityNamedBarrier = 59, + CapabilityPipeStorage = 60, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + CapabilitySubgroupVoteKHR = 4431, + CapabilityStorageBuffer16BitAccess = 4433, + CapabilityStorageUniformBufferBlock16 = 4433, + CapabilityStorageUniform16 = 4434, + CapabilityUniformAndStorageBuffer16BitAccess = 4434, + CapabilityStoragePushConstant16 = 4435, + CapabilityStorageInputOutput16 = 4436, + CapabilityDeviceGroup = 4437, + CapabilityMultiView = 4439, + CapabilityVariablePointersStorageBuffer = 4441, + CapabilityVariablePointers = 4442, + CapabilityAtomicStorageOps = 4445, + CapabilitySampleMaskPostDepthCoverage = 4447, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilityMax = 0x7fffffff, +}; + +enum Op { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + OpMax = 0x7fffffff, +}; + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/ext/vulkan/spirv.hpp11 b/ext/vulkan/spirv.hpp11 index b99396378c..c345f6da98 100644 --- a/ext/vulkan/spirv.hpp11 +++ b/ext/vulkan/spirv.hpp11 @@ -1,974 +1,1019 @@ -// Copyright (c) 2014-2017 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and/or associated documentation files (the "Materials"), -// to deal in the Materials without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Materials, and to permit persons to whom the -// Materials are furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Materials. -// -// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -// IN THE MATERIALS. - -// This header is automatically generated by the same tool that creates -// the Binary Section of the SPIR-V specification. - -// Enumeration tokens for SPIR-V, in various styles: -// C, C++, C++11, JSON, Lua, Python -// -// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL -// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL -// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL -// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL -// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] -// -// Some tokens act like mask values, which can be OR'd together, -// while others are mutually exclusive. The mask-like ones have -// "Mask" in their name, and a parallel enum that has the shift -// amount (1 << x) for each corresponding enumerant. - -#ifndef spirv_HPP -#define spirv_HPP - -namespace spv { - -typedef unsigned int Id; - -#define SPV_VERSION 0x10100 -#define SPV_REVISION 6 - -static const unsigned int MagicNumber = 0x07230203; -static const unsigned int Version = 0x00010100; -static const unsigned int Revision = 6; -static const unsigned int OpCodeMask = 0xffff; -static const unsigned int WordCountShift = 16; - -enum class SourceLanguage : unsigned { - Unknown = 0, - ESSL = 1, - GLSL = 2, - OpenCL_C = 3, - OpenCL_CPP = 4, - Max = 0x7fffffff, -}; - -enum class ExecutionModel : unsigned { - Vertex = 0, - TessellationControl = 1, - TessellationEvaluation = 2, - Geometry = 3, - Fragment = 4, - GLCompute = 5, - Kernel = 6, - Max = 0x7fffffff, -}; - -enum class AddressingModel : unsigned { - Logical = 0, - Physical32 = 1, - Physical64 = 2, - Max = 0x7fffffff, -}; - -enum class MemoryModel : unsigned { - Simple = 0, - GLSL450 = 1, - OpenCL = 2, - Max = 0x7fffffff, -}; - -enum class ExecutionMode : unsigned { - Invocations = 0, - SpacingEqual = 1, - SpacingFractionalEven = 2, - SpacingFractionalOdd = 3, - VertexOrderCw = 4, - VertexOrderCcw = 5, - PixelCenterInteger = 6, - OriginUpperLeft = 7, - OriginLowerLeft = 8, - EarlyFragmentTests = 9, - PointMode = 10, - Xfb = 11, - DepthReplacing = 12, - DepthGreater = 14, - DepthLess = 15, - DepthUnchanged = 16, - LocalSize = 17, - LocalSizeHint = 18, - InputPoints = 19, - InputLines = 20, - InputLinesAdjacency = 21, - Triangles = 22, - InputTrianglesAdjacency = 23, - Quads = 24, - Isolines = 25, - OutputVertices = 26, - OutputPoints = 27, - OutputLineStrip = 28, - OutputTriangleStrip = 29, - VecTypeHint = 30, - ContractionOff = 31, - Initializer = 33, - Finalizer = 34, - SubgroupSize = 35, - SubgroupsPerWorkgroup = 36, - Max = 0x7fffffff, -}; - -enum class StorageClass : unsigned { - UniformConstant = 0, - Input = 1, - Uniform = 2, - Output = 3, - Workgroup = 4, - CrossWorkgroup = 5, - Private = 6, - Function = 7, - Generic = 8, - PushConstant = 9, - AtomicCounter = 10, - Image = 11, - Max = 0x7fffffff, -}; - -enum class Dim : unsigned { - Dim1D = 0, - Dim2D = 1, - Dim3D = 2, - Cube = 3, - Rect = 4, - Buffer = 5, - SubpassData = 6, - Max = 0x7fffffff, -}; - -enum class SamplerAddressingMode : unsigned { - None = 0, - ClampToEdge = 1, - Clamp = 2, - Repeat = 3, - RepeatMirrored = 4, - Max = 0x7fffffff, -}; - -enum class SamplerFilterMode : unsigned { - Nearest = 0, - Linear = 1, - Max = 0x7fffffff, -}; - -enum class ImageFormat : unsigned { - Unknown = 0, - Rgba32f = 1, - Rgba16f = 2, - R32f = 3, - Rgba8 = 4, - Rgba8Snorm = 5, - Rg32f = 6, - Rg16f = 7, - R11fG11fB10f = 8, - R16f = 9, - Rgba16 = 10, - Rgb10A2 = 11, - Rg16 = 12, - Rg8 = 13, - R16 = 14, - R8 = 15, - Rgba16Snorm = 16, - Rg16Snorm = 17, - Rg8Snorm = 18, - R16Snorm = 19, - R8Snorm = 20, - Rgba32i = 21, - Rgba16i = 22, - Rgba8i = 23, - R32i = 24, - Rg32i = 25, - Rg16i = 26, - Rg8i = 27, - R16i = 28, - R8i = 29, - Rgba32ui = 30, - Rgba16ui = 31, - Rgba8ui = 32, - R32ui = 33, - Rgb10a2ui = 34, - Rg32ui = 35, - Rg16ui = 36, - Rg8ui = 37, - R16ui = 38, - R8ui = 39, - Max = 0x7fffffff, -}; - -enum class ImageChannelOrder : unsigned { - R = 0, - A = 1, - RG = 2, - RA = 3, - RGB = 4, - RGBA = 5, - BGRA = 6, - ARGB = 7, - Intensity = 8, - Luminance = 9, - Rx = 10, - RGx = 11, - RGBx = 12, - Depth = 13, - DepthStencil = 14, - sRGB = 15, - sRGBx = 16, - sRGBA = 17, - sBGRA = 18, - ABGR = 19, - Max = 0x7fffffff, -}; - -enum class ImageChannelDataType : unsigned { - SnormInt8 = 0, - SnormInt16 = 1, - UnormInt8 = 2, - UnormInt16 = 3, - UnormShort565 = 4, - UnormShort555 = 5, - UnormInt101010 = 6, - SignedInt8 = 7, - SignedInt16 = 8, - SignedInt32 = 9, - UnsignedInt8 = 10, - UnsignedInt16 = 11, - UnsignedInt32 = 12, - HalfFloat = 13, - Float = 14, - UnormInt24 = 15, - UnormInt101010_2 = 16, - Max = 0x7fffffff, -}; - -enum class ImageOperandsShift : unsigned { - Bias = 0, - Lod = 1, - Grad = 2, - ConstOffset = 3, - Offset = 4, - ConstOffsets = 5, - Sample = 6, - MinLod = 7, - Max = 0x7fffffff, -}; - -enum class ImageOperandsMask : unsigned { - MaskNone = 0, - Bias = 0x00000001, - Lod = 0x00000002, - Grad = 0x00000004, - ConstOffset = 0x00000008, - Offset = 0x00000010, - ConstOffsets = 0x00000020, - Sample = 0x00000040, - MinLod = 0x00000080, -}; - -enum class FPFastMathModeShift : unsigned { - NotNaN = 0, - NotInf = 1, - NSZ = 2, - AllowRecip = 3, - Fast = 4, - Max = 0x7fffffff, -}; - -enum class FPFastMathModeMask : unsigned { - MaskNone = 0, - NotNaN = 0x00000001, - NotInf = 0x00000002, - NSZ = 0x00000004, - AllowRecip = 0x00000008, - Fast = 0x00000010, -}; - -enum class FPRoundingMode : unsigned { - RTE = 0, - RTZ = 1, - RTP = 2, - RTN = 3, - Max = 0x7fffffff, -}; - -enum class LinkageType : unsigned { - Export = 0, - Import = 1, - Max = 0x7fffffff, -}; - -enum class AccessQualifier : unsigned { - ReadOnly = 0, - WriteOnly = 1, - ReadWrite = 2, - Max = 0x7fffffff, -}; - -enum class FunctionParameterAttribute : unsigned { - Zext = 0, - Sext = 1, - ByVal = 2, - Sret = 3, - NoAlias = 4, - NoCapture = 5, - NoWrite = 6, - NoReadWrite = 7, - Max = 0x7fffffff, -}; - -enum class Decoration : unsigned { - RelaxedPrecision = 0, - SpecId = 1, - Block = 2, - BufferBlock = 3, - RowMajor = 4, - ColMajor = 5, - ArrayStride = 6, - MatrixStride = 7, - GLSLShared = 8, - GLSLPacked = 9, - CPacked = 10, - BuiltIn = 11, - NoPerspective = 13, - Flat = 14, - Patch = 15, - Centroid = 16, - Sample = 17, - Invariant = 18, - Restrict = 19, - Aliased = 20, - Volatile = 21, - Constant = 22, - Coherent = 23, - NonWritable = 24, - NonReadable = 25, - Uniform = 26, - SaturatedConversion = 28, - Stream = 29, - Location = 30, - Component = 31, - Index = 32, - Binding = 33, - DescriptorSet = 34, - Offset = 35, - XfbBuffer = 36, - XfbStride = 37, - FuncParamAttr = 38, - FPRoundingMode = 39, - FPFastMathMode = 40, - LinkageAttributes = 41, - NoContraction = 42, - InputAttachmentIndex = 43, - Alignment = 44, - MaxByteOffset = 45, - OverrideCoverageNV = 5248, - PassthroughNV = 5250, - ViewportRelativeNV = 5252, - SecondaryViewportRelativeNV = 5256, - Max = 0x7fffffff, -}; - -enum class BuiltIn : unsigned { - Position = 0, - PointSize = 1, - ClipDistance = 3, - CullDistance = 4, - VertexId = 5, - InstanceId = 6, - PrimitiveId = 7, - InvocationId = 8, - Layer = 9, - ViewportIndex = 10, - TessLevelOuter = 11, - TessLevelInner = 12, - TessCoord = 13, - PatchVertices = 14, - FragCoord = 15, - PointCoord = 16, - FrontFacing = 17, - SampleId = 18, - SamplePosition = 19, - SampleMask = 20, - FragDepth = 22, - HelperInvocation = 23, - NumWorkgroups = 24, - WorkgroupSize = 25, - WorkgroupId = 26, - LocalInvocationId = 27, - GlobalInvocationId = 28, - LocalInvocationIndex = 29, - WorkDim = 30, - GlobalSize = 31, - EnqueuedWorkgroupSize = 32, - GlobalOffset = 33, - GlobalLinearId = 34, - SubgroupSize = 36, - SubgroupMaxSize = 37, - NumSubgroups = 38, - NumEnqueuedSubgroups = 39, - SubgroupId = 40, - SubgroupLocalInvocationId = 41, - VertexIndex = 42, - InstanceIndex = 43, - SubgroupEqMaskKHR = 4416, - SubgroupGeMaskKHR = 4417, - SubgroupGtMaskKHR = 4418, - SubgroupLeMaskKHR = 4419, - SubgroupLtMaskKHR = 4420, - BaseVertex = 4424, - BaseInstance = 4425, - DrawIndex = 4426, - DeviceIndex = 4438, - ViewIndex = 4440, - ViewportMaskNV = 5253, - SecondaryPositionNV = 5257, - SecondaryViewportMaskNV = 5258, - PositionPerViewNV = 5261, - ViewportMaskPerViewNV = 5262, - Max = 0x7fffffff, -}; - -enum class SelectionControlShift : unsigned { - Flatten = 0, - DontFlatten = 1, - Max = 0x7fffffff, -}; - -enum class SelectionControlMask : unsigned { - MaskNone = 0, - Flatten = 0x00000001, - DontFlatten = 0x00000002, -}; - -enum class LoopControlShift : unsigned { - Unroll = 0, - DontUnroll = 1, - DependencyInfinite = 2, - DependencyLength = 3, - Max = 0x7fffffff, -}; - -enum class LoopControlMask : unsigned { - MaskNone = 0, - Unroll = 0x00000001, - DontUnroll = 0x00000002, - DependencyInfinite = 0x00000004, - DependencyLength = 0x00000008, -}; - -enum class FunctionControlShift : unsigned { - Inline = 0, - DontInline = 1, - Pure = 2, - Const = 3, - Max = 0x7fffffff, -}; - -enum class FunctionControlMask : unsigned { - MaskNone = 0, - Inline = 0x00000001, - DontInline = 0x00000002, - Pure = 0x00000004, - Const = 0x00000008, -}; - -enum class MemorySemanticsShift : unsigned { - Acquire = 1, - Release = 2, - AcquireRelease = 3, - SequentiallyConsistent = 4, - UniformMemory = 6, - SubgroupMemory = 7, - WorkgroupMemory = 8, - CrossWorkgroupMemory = 9, - AtomicCounterMemory = 10, - ImageMemory = 11, - Max = 0x7fffffff, -}; - -enum class MemorySemanticsMask : unsigned { - MaskNone = 0, - Acquire = 0x00000002, - Release = 0x00000004, - AcquireRelease = 0x00000008, - SequentiallyConsistent = 0x00000010, - UniformMemory = 0x00000040, - SubgroupMemory = 0x00000080, - WorkgroupMemory = 0x00000100, - CrossWorkgroupMemory = 0x00000200, - AtomicCounterMemory = 0x00000400, - ImageMemory = 0x00000800, -}; - -enum class MemoryAccessShift : unsigned { - Volatile = 0, - Aligned = 1, - Nontemporal = 2, - Max = 0x7fffffff, -}; - -enum class MemoryAccessMask : unsigned { - MaskNone = 0, - Volatile = 0x00000001, - Aligned = 0x00000002, - Nontemporal = 0x00000004, -}; - -enum class Scope : unsigned { - CrossDevice = 0, - Device = 1, - Workgroup = 2, - Subgroup = 3, - Invocation = 4, - Max = 0x7fffffff, -}; - -enum class GroupOperation : unsigned { - Reduce = 0, - InclusiveScan = 1, - ExclusiveScan = 2, - Max = 0x7fffffff, -}; - -enum class KernelEnqueueFlags : unsigned { - NoWait = 0, - WaitKernel = 1, - WaitWorkGroup = 2, - Max = 0x7fffffff, -}; - -enum class KernelProfilingInfoShift : unsigned { - CmdExecTime = 0, - Max = 0x7fffffff, -}; - -enum class KernelProfilingInfoMask : unsigned { - MaskNone = 0, - CmdExecTime = 0x00000001, -}; - -enum class Capability : unsigned { - Matrix = 0, - Shader = 1, - Geometry = 2, - Tessellation = 3, - Addresses = 4, - Linkage = 5, - Kernel = 6, - Vector16 = 7, - Float16Buffer = 8, - Float16 = 9, - Float64 = 10, - Int64 = 11, - Int64Atomics = 12, - ImageBasic = 13, - ImageReadWrite = 14, - ImageMipmap = 15, - Pipes = 17, - Groups = 18, - DeviceEnqueue = 19, - LiteralSampler = 20, - AtomicStorage = 21, - Int16 = 22, - TessellationPointSize = 23, - GeometryPointSize = 24, - ImageGatherExtended = 25, - StorageImageMultisample = 27, - UniformBufferArrayDynamicIndexing = 28, - SampledImageArrayDynamicIndexing = 29, - StorageBufferArrayDynamicIndexing = 30, - StorageImageArrayDynamicIndexing = 31, - ClipDistance = 32, - CullDistance = 33, - ImageCubeArray = 34, - SampleRateShading = 35, - ImageRect = 36, - SampledRect = 37, - GenericPointer = 38, - Int8 = 39, - InputAttachment = 40, - SparseResidency = 41, - MinLod = 42, - Sampled1D = 43, - Image1D = 44, - SampledCubeArray = 45, - SampledBuffer = 46, - ImageBuffer = 47, - ImageMSArray = 48, - StorageImageExtendedFormats = 49, - ImageQuery = 50, - DerivativeControl = 51, - InterpolationFunction = 52, - TransformFeedback = 53, - GeometryStreams = 54, - StorageImageReadWithoutFormat = 55, - StorageImageWriteWithoutFormat = 56, - MultiViewport = 57, - SubgroupDispatch = 58, - NamedBarrier = 59, - PipeStorage = 60, - SubgroupBallotKHR = 4423, - DrawParameters = 4427, - SubgroupVoteKHR = 4431, - StorageUniformBufferBlock16 = 4433, - StorageUniform16 = 4434, - StoragePushConstant16 = 4435, - StorageInputOutput16 = 4436, - DeviceGroup = 4437, - MultiView = 4439, - SampleMaskOverrideCoverageNV = 5249, - GeometryShaderPassthroughNV = 5251, - ShaderViewportIndexLayerNV = 5254, - ShaderViewportMaskNV = 5255, - ShaderStereoViewNV = 5259, - PerViewAttributesNV = 5260, - Max = 0x7fffffff, -}; - -enum class Op : unsigned { - OpNop = 0, - OpUndef = 1, - OpSourceContinued = 2, - OpSource = 3, - OpSourceExtension = 4, - OpName = 5, - OpMemberName = 6, - OpString = 7, - OpLine = 8, - OpExtension = 10, - OpExtInstImport = 11, - OpExtInst = 12, - OpMemoryModel = 14, - OpEntryPoint = 15, - OpExecutionMode = 16, - OpCapability = 17, - OpTypeVoid = 19, - OpTypeBool = 20, - OpTypeInt = 21, - OpTypeFloat = 22, - OpTypeVector = 23, - OpTypeMatrix = 24, - OpTypeImage = 25, - OpTypeSampler = 26, - OpTypeSampledImage = 27, - OpTypeArray = 28, - OpTypeRuntimeArray = 29, - OpTypeStruct = 30, - OpTypeOpaque = 31, - OpTypePointer = 32, - OpTypeFunction = 33, - OpTypeEvent = 34, - OpTypeDeviceEvent = 35, - OpTypeReserveId = 36, - OpTypeQueue = 37, - OpTypePipe = 38, - OpTypeForwardPointer = 39, - OpConstantTrue = 41, - OpConstantFalse = 42, - OpConstant = 43, - OpConstantComposite = 44, - OpConstantSampler = 45, - OpConstantNull = 46, - OpSpecConstantTrue = 48, - OpSpecConstantFalse = 49, - OpSpecConstant = 50, - OpSpecConstantComposite = 51, - OpSpecConstantOp = 52, - OpFunction = 54, - OpFunctionParameter = 55, - OpFunctionEnd = 56, - OpFunctionCall = 57, - OpVariable = 59, - OpImageTexelPointer = 60, - OpLoad = 61, - OpStore = 62, - OpCopyMemory = 63, - OpCopyMemorySized = 64, - OpAccessChain = 65, - OpInBoundsAccessChain = 66, - OpPtrAccessChain = 67, - OpArrayLength = 68, - OpGenericPtrMemSemantics = 69, - OpInBoundsPtrAccessChain = 70, - OpDecorate = 71, - OpMemberDecorate = 72, - OpDecorationGroup = 73, - OpGroupDecorate = 74, - OpGroupMemberDecorate = 75, - OpVectorExtractDynamic = 77, - OpVectorInsertDynamic = 78, - OpVectorShuffle = 79, - OpCompositeConstruct = 80, - OpCompositeExtract = 81, - OpCompositeInsert = 82, - OpCopyObject = 83, - OpTranspose = 84, - OpSampledImage = 86, - OpImageSampleImplicitLod = 87, - OpImageSampleExplicitLod = 88, - OpImageSampleDrefImplicitLod = 89, - OpImageSampleDrefExplicitLod = 90, - OpImageSampleProjImplicitLod = 91, - OpImageSampleProjExplicitLod = 92, - OpImageSampleProjDrefImplicitLod = 93, - OpImageSampleProjDrefExplicitLod = 94, - OpImageFetch = 95, - OpImageGather = 96, - OpImageDrefGather = 97, - OpImageRead = 98, - OpImageWrite = 99, - OpImage = 100, - OpImageQueryFormat = 101, - OpImageQueryOrder = 102, - OpImageQuerySizeLod = 103, - OpImageQuerySize = 104, - OpImageQueryLod = 105, - OpImageQueryLevels = 106, - OpImageQuerySamples = 107, - OpConvertFToU = 109, - OpConvertFToS = 110, - OpConvertSToF = 111, - OpConvertUToF = 112, - OpUConvert = 113, - OpSConvert = 114, - OpFConvert = 115, - OpQuantizeToF16 = 116, - OpConvertPtrToU = 117, - OpSatConvertSToU = 118, - OpSatConvertUToS = 119, - OpConvertUToPtr = 120, - OpPtrCastToGeneric = 121, - OpGenericCastToPtr = 122, - OpGenericCastToPtrExplicit = 123, - OpBitcast = 124, - OpSNegate = 126, - OpFNegate = 127, - OpIAdd = 128, - OpFAdd = 129, - OpISub = 130, - OpFSub = 131, - OpIMul = 132, - OpFMul = 133, - OpUDiv = 134, - OpSDiv = 135, - OpFDiv = 136, - OpUMod = 137, - OpSRem = 138, - OpSMod = 139, - OpFRem = 140, - OpFMod = 141, - OpVectorTimesScalar = 142, - OpMatrixTimesScalar = 143, - OpVectorTimesMatrix = 144, - OpMatrixTimesVector = 145, - OpMatrixTimesMatrix = 146, - OpOuterProduct = 147, - OpDot = 148, - OpIAddCarry = 149, - OpISubBorrow = 150, - OpUMulExtended = 151, - OpSMulExtended = 152, - OpAny = 154, - OpAll = 155, - OpIsNan = 156, - OpIsInf = 157, - OpIsFinite = 158, - OpIsNormal = 159, - OpSignBitSet = 160, - OpLessOrGreater = 161, - OpOrdered = 162, - OpUnordered = 163, - OpLogicalEqual = 164, - OpLogicalNotEqual = 165, - OpLogicalOr = 166, - OpLogicalAnd = 167, - OpLogicalNot = 168, - OpSelect = 169, - OpIEqual = 170, - OpINotEqual = 171, - OpUGreaterThan = 172, - OpSGreaterThan = 173, - OpUGreaterThanEqual = 174, - OpSGreaterThanEqual = 175, - OpULessThan = 176, - OpSLessThan = 177, - OpULessThanEqual = 178, - OpSLessThanEqual = 179, - OpFOrdEqual = 180, - OpFUnordEqual = 181, - OpFOrdNotEqual = 182, - OpFUnordNotEqual = 183, - OpFOrdLessThan = 184, - OpFUnordLessThan = 185, - OpFOrdGreaterThan = 186, - OpFUnordGreaterThan = 187, - OpFOrdLessThanEqual = 188, - OpFUnordLessThanEqual = 189, - OpFOrdGreaterThanEqual = 190, - OpFUnordGreaterThanEqual = 191, - OpShiftRightLogical = 194, - OpShiftRightArithmetic = 195, - OpShiftLeftLogical = 196, - OpBitwiseOr = 197, - OpBitwiseXor = 198, - OpBitwiseAnd = 199, - OpNot = 200, - OpBitFieldInsert = 201, - OpBitFieldSExtract = 202, - OpBitFieldUExtract = 203, - OpBitReverse = 204, - OpBitCount = 205, - OpDPdx = 207, - OpDPdy = 208, - OpFwidth = 209, - OpDPdxFine = 210, - OpDPdyFine = 211, - OpFwidthFine = 212, - OpDPdxCoarse = 213, - OpDPdyCoarse = 214, - OpFwidthCoarse = 215, - OpEmitVertex = 218, - OpEndPrimitive = 219, - OpEmitStreamVertex = 220, - OpEndStreamPrimitive = 221, - OpControlBarrier = 224, - OpMemoryBarrier = 225, - OpAtomicLoad = 227, - OpAtomicStore = 228, - OpAtomicExchange = 229, - OpAtomicCompareExchange = 230, - OpAtomicCompareExchangeWeak = 231, - OpAtomicIIncrement = 232, - OpAtomicIDecrement = 233, - OpAtomicIAdd = 234, - OpAtomicISub = 235, - OpAtomicSMin = 236, - OpAtomicUMin = 237, - OpAtomicSMax = 238, - OpAtomicUMax = 239, - OpAtomicAnd = 240, - OpAtomicOr = 241, - OpAtomicXor = 242, - OpPhi = 245, - OpLoopMerge = 246, - OpSelectionMerge = 247, - OpLabel = 248, - OpBranch = 249, - OpBranchConditional = 250, - OpSwitch = 251, - OpKill = 252, - OpReturn = 253, - OpReturnValue = 254, - OpUnreachable = 255, - OpLifetimeStart = 256, - OpLifetimeStop = 257, - OpGroupAsyncCopy = 259, - OpGroupWaitEvents = 260, - OpGroupAll = 261, - OpGroupAny = 262, - OpGroupBroadcast = 263, - OpGroupIAdd = 264, - OpGroupFAdd = 265, - OpGroupFMin = 266, - OpGroupUMin = 267, - OpGroupSMin = 268, - OpGroupFMax = 269, - OpGroupUMax = 270, - OpGroupSMax = 271, - OpReadPipe = 274, - OpWritePipe = 275, - OpReservedReadPipe = 276, - OpReservedWritePipe = 277, - OpReserveReadPipePackets = 278, - OpReserveWritePipePackets = 279, - OpCommitReadPipe = 280, - OpCommitWritePipe = 281, - OpIsValidReserveId = 282, - OpGetNumPipePackets = 283, - OpGetMaxPipePackets = 284, - OpGroupReserveReadPipePackets = 285, - OpGroupReserveWritePipePackets = 286, - OpGroupCommitReadPipe = 287, - OpGroupCommitWritePipe = 288, - OpEnqueueMarker = 291, - OpEnqueueKernel = 292, - OpGetKernelNDrangeSubGroupCount = 293, - OpGetKernelNDrangeMaxSubGroupSize = 294, - OpGetKernelWorkGroupSize = 295, - OpGetKernelPreferredWorkGroupSizeMultiple = 296, - OpRetainEvent = 297, - OpReleaseEvent = 298, - OpCreateUserEvent = 299, - OpIsValidEvent = 300, - OpSetUserEventStatus = 301, - OpCaptureEventProfilingInfo = 302, - OpGetDefaultQueue = 303, - OpBuildNDRange = 304, - OpImageSparseSampleImplicitLod = 305, - OpImageSparseSampleExplicitLod = 306, - OpImageSparseSampleDrefImplicitLod = 307, - OpImageSparseSampleDrefExplicitLod = 308, - OpImageSparseSampleProjImplicitLod = 309, - OpImageSparseSampleProjExplicitLod = 310, - OpImageSparseSampleProjDrefImplicitLod = 311, - OpImageSparseSampleProjDrefExplicitLod = 312, - OpImageSparseFetch = 313, - OpImageSparseGather = 314, - OpImageSparseDrefGather = 315, - OpImageSparseTexelsResident = 316, - OpNoLine = 317, - OpAtomicFlagTestAndSet = 318, - OpAtomicFlagClear = 319, - OpImageSparseRead = 320, - OpSizeOf = 321, - OpTypePipeStorage = 322, - OpConstantPipeStorage = 323, - OpCreatePipeFromPipeStorage = 324, - OpGetKernelLocalSizeForSubgroupCount = 325, - OpGetKernelMaxNumSubgroups = 326, - OpTypeNamedBarrier = 327, - OpNamedBarrierInitialize = 328, - OpMemoryNamedBarrier = 329, - OpModuleProcessed = 330, - OpSubgroupBallotKHR = 4421, - OpSubgroupFirstInvocationKHR = 4422, - OpSubgroupAllKHR = 4428, - OpSubgroupAnyKHR = 4429, - OpSubgroupAllEqualKHR = 4430, - OpSubgroupReadInvocationKHR = 4432, - Max = 0x7fffffff, -}; - -// Overload operator| for mask bit combining - -inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } -inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } -inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } -inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } -inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } -inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } -inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } -inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } - -} // end namespace spv - -#endif // #ifndef spirv_HPP - +// Copyright (c) 2014-2017 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +// This header is automatically generated by the same tool that creates +// the Binary Section of the SPIR-V specification. + +// Enumeration tokens for SPIR-V, in various styles: +// C, C++, C++11, JSON, Lua, Python +// +// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +// +// Some tokens act like mask values, which can be OR'd together, +// while others are mutually exclusive. The mask-like ones have +// "Mask" in their name, and a parallel enum that has the shift +// amount (1 << x) for each corresponding enumerant. + +#ifndef spirv_HPP +#define spirv_HPP + +namespace spv { + +typedef unsigned int Id; + +#define SPV_VERSION 0x10100 +#define SPV_REVISION 8 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010100; +static const unsigned int Revision = 8; +static const unsigned int OpCodeMask = 0xffff; +static const unsigned int WordCountShift = 16; + +enum class SourceLanguage : unsigned { + Unknown = 0, + ESSL = 1, + GLSL = 2, + OpenCL_C = 3, + OpenCL_CPP = 4, + HLSL = 5, + Max = 0x7fffffff, +}; + +enum class ExecutionModel : unsigned { + Vertex = 0, + TessellationControl = 1, + TessellationEvaluation = 2, + Geometry = 3, + Fragment = 4, + GLCompute = 5, + Kernel = 6, + Max = 0x7fffffff, +}; + +enum class AddressingModel : unsigned { + Logical = 0, + Physical32 = 1, + Physical64 = 2, + Max = 0x7fffffff, +}; + +enum class MemoryModel : unsigned { + Simple = 0, + GLSL450 = 1, + OpenCL = 2, + Max = 0x7fffffff, +}; + +enum class ExecutionMode : unsigned { + Invocations = 0, + SpacingEqual = 1, + SpacingFractionalEven = 2, + SpacingFractionalOdd = 3, + VertexOrderCw = 4, + VertexOrderCcw = 5, + PixelCenterInteger = 6, + OriginUpperLeft = 7, + OriginLowerLeft = 8, + EarlyFragmentTests = 9, + PointMode = 10, + Xfb = 11, + DepthReplacing = 12, + DepthGreater = 14, + DepthLess = 15, + DepthUnchanged = 16, + LocalSize = 17, + LocalSizeHint = 18, + InputPoints = 19, + InputLines = 20, + InputLinesAdjacency = 21, + Triangles = 22, + InputTrianglesAdjacency = 23, + Quads = 24, + Isolines = 25, + OutputVertices = 26, + OutputPoints = 27, + OutputLineStrip = 28, + OutputTriangleStrip = 29, + VecTypeHint = 30, + ContractionOff = 31, + Initializer = 33, + Finalizer = 34, + SubgroupSize = 35, + SubgroupsPerWorkgroup = 36, + PostDepthCoverage = 4446, + StencilRefReplacingEXT = 5027, + Max = 0x7fffffff, +}; + +enum class StorageClass : unsigned { + UniformConstant = 0, + Input = 1, + Uniform = 2, + Output = 3, + Workgroup = 4, + CrossWorkgroup = 5, + Private = 6, + Function = 7, + Generic = 8, + PushConstant = 9, + AtomicCounter = 10, + Image = 11, + StorageBuffer = 12, + Max = 0x7fffffff, +}; + +enum class Dim : unsigned { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + Cube = 3, + Rect = 4, + Buffer = 5, + SubpassData = 6, + Max = 0x7fffffff, +}; + +enum class SamplerAddressingMode : unsigned { + None = 0, + ClampToEdge = 1, + Clamp = 2, + Repeat = 3, + RepeatMirrored = 4, + Max = 0x7fffffff, +}; + +enum class SamplerFilterMode : unsigned { + Nearest = 0, + Linear = 1, + Max = 0x7fffffff, +}; + +enum class ImageFormat : unsigned { + Unknown = 0, + Rgba32f = 1, + Rgba16f = 2, + R32f = 3, + Rgba8 = 4, + Rgba8Snorm = 5, + Rg32f = 6, + Rg16f = 7, + R11fG11fB10f = 8, + R16f = 9, + Rgba16 = 10, + Rgb10A2 = 11, + Rg16 = 12, + Rg8 = 13, + R16 = 14, + R8 = 15, + Rgba16Snorm = 16, + Rg16Snorm = 17, + Rg8Snorm = 18, + R16Snorm = 19, + R8Snorm = 20, + Rgba32i = 21, + Rgba16i = 22, + Rgba8i = 23, + R32i = 24, + Rg32i = 25, + Rg16i = 26, + Rg8i = 27, + R16i = 28, + R8i = 29, + Rgba32ui = 30, + Rgba16ui = 31, + Rgba8ui = 32, + R32ui = 33, + Rgb10a2ui = 34, + Rg32ui = 35, + Rg16ui = 36, + Rg8ui = 37, + R16ui = 38, + R8ui = 39, + Max = 0x7fffffff, +}; + +enum class ImageChannelOrder : unsigned { + R = 0, + A = 1, + RG = 2, + RA = 3, + RGB = 4, + RGBA = 5, + BGRA = 6, + ARGB = 7, + Intensity = 8, + Luminance = 9, + Rx = 10, + RGx = 11, + RGBx = 12, + Depth = 13, + DepthStencil = 14, + sRGB = 15, + sRGBx = 16, + sRGBA = 17, + sBGRA = 18, + ABGR = 19, + Max = 0x7fffffff, +}; + +enum class ImageChannelDataType : unsigned { + SnormInt8 = 0, + SnormInt16 = 1, + UnormInt8 = 2, + UnormInt16 = 3, + UnormShort565 = 4, + UnormShort555 = 5, + UnormInt101010 = 6, + SignedInt8 = 7, + SignedInt16 = 8, + SignedInt32 = 9, + UnsignedInt8 = 10, + UnsignedInt16 = 11, + UnsignedInt32 = 12, + HalfFloat = 13, + Float = 14, + UnormInt24 = 15, + UnormInt101010_2 = 16, + Max = 0x7fffffff, +}; + +enum class ImageOperandsShift : unsigned { + Bias = 0, + Lod = 1, + Grad = 2, + ConstOffset = 3, + Offset = 4, + ConstOffsets = 5, + Sample = 6, + MinLod = 7, + Max = 0x7fffffff, +}; + +enum class ImageOperandsMask : unsigned { + MaskNone = 0, + Bias = 0x00000001, + Lod = 0x00000002, + Grad = 0x00000004, + ConstOffset = 0x00000008, + Offset = 0x00000010, + ConstOffsets = 0x00000020, + Sample = 0x00000040, + MinLod = 0x00000080, +}; + +enum class FPFastMathModeShift : unsigned { + NotNaN = 0, + NotInf = 1, + NSZ = 2, + AllowRecip = 3, + Fast = 4, + Max = 0x7fffffff, +}; + +enum class FPFastMathModeMask : unsigned { + MaskNone = 0, + NotNaN = 0x00000001, + NotInf = 0x00000002, + NSZ = 0x00000004, + AllowRecip = 0x00000008, + Fast = 0x00000010, +}; + +enum class FPRoundingMode : unsigned { + RTE = 0, + RTZ = 1, + RTP = 2, + RTN = 3, + Max = 0x7fffffff, +}; + +enum class LinkageType : unsigned { + Export = 0, + Import = 1, + Max = 0x7fffffff, +}; + +enum class AccessQualifier : unsigned { + ReadOnly = 0, + WriteOnly = 1, + ReadWrite = 2, + Max = 0x7fffffff, +}; + +enum class FunctionParameterAttribute : unsigned { + Zext = 0, + Sext = 1, + ByVal = 2, + Sret = 3, + NoAlias = 4, + NoCapture = 5, + NoWrite = 6, + NoReadWrite = 7, + Max = 0x7fffffff, +}; + +enum class Decoration : unsigned { + RelaxedPrecision = 0, + SpecId = 1, + Block = 2, + BufferBlock = 3, + RowMajor = 4, + ColMajor = 5, + ArrayStride = 6, + MatrixStride = 7, + GLSLShared = 8, + GLSLPacked = 9, + CPacked = 10, + BuiltIn = 11, + NoPerspective = 13, + Flat = 14, + Patch = 15, + Centroid = 16, + Sample = 17, + Invariant = 18, + Restrict = 19, + Aliased = 20, + Volatile = 21, + Constant = 22, + Coherent = 23, + NonWritable = 24, + NonReadable = 25, + Uniform = 26, + SaturatedConversion = 28, + Stream = 29, + Location = 30, + Component = 31, + Index = 32, + Binding = 33, + DescriptorSet = 34, + Offset = 35, + XfbBuffer = 36, + XfbStride = 37, + FuncParamAttr = 38, + FPRoundingMode = 39, + FPFastMathMode = 40, + LinkageAttributes = 41, + NoContraction = 42, + InputAttachmentIndex = 43, + Alignment = 44, + MaxByteOffset = 45, + ExplicitInterpAMD = 4999, + OverrideCoverageNV = 5248, + PassthroughNV = 5250, + ViewportRelativeNV = 5252, + SecondaryViewportRelativeNV = 5256, + Max = 0x7fffffff, +}; + +enum class BuiltIn : unsigned { + Position = 0, + PointSize = 1, + ClipDistance = 3, + CullDistance = 4, + VertexId = 5, + InstanceId = 6, + PrimitiveId = 7, + InvocationId = 8, + Layer = 9, + ViewportIndex = 10, + TessLevelOuter = 11, + TessLevelInner = 12, + TessCoord = 13, + PatchVertices = 14, + FragCoord = 15, + PointCoord = 16, + FrontFacing = 17, + SampleId = 18, + SamplePosition = 19, + SampleMask = 20, + FragDepth = 22, + HelperInvocation = 23, + NumWorkgroups = 24, + WorkgroupSize = 25, + WorkgroupId = 26, + LocalInvocationId = 27, + GlobalInvocationId = 28, + LocalInvocationIndex = 29, + WorkDim = 30, + GlobalSize = 31, + EnqueuedWorkgroupSize = 32, + GlobalOffset = 33, + GlobalLinearId = 34, + SubgroupSize = 36, + SubgroupMaxSize = 37, + NumSubgroups = 38, + NumEnqueuedSubgroups = 39, + SubgroupId = 40, + SubgroupLocalInvocationId = 41, + VertexIndex = 42, + InstanceIndex = 43, + SubgroupEqMaskKHR = 4416, + SubgroupGeMaskKHR = 4417, + SubgroupGtMaskKHR = 4418, + SubgroupLeMaskKHR = 4419, + SubgroupLtMaskKHR = 4420, + BaseVertex = 4424, + BaseInstance = 4425, + DrawIndex = 4426, + DeviceIndex = 4438, + ViewIndex = 4440, + BaryCoordNoPerspAMD = 4992, + BaryCoordNoPerspCentroidAMD = 4993, + BaryCoordNoPerspSampleAMD = 4994, + BaryCoordSmoothAMD = 4995, + BaryCoordSmoothCentroidAMD = 4996, + BaryCoordSmoothSampleAMD = 4997, + BaryCoordPullModelAMD = 4998, + FragStencilRefEXT = 5014, + ViewportMaskNV = 5253, + SecondaryPositionNV = 5257, + SecondaryViewportMaskNV = 5258, + PositionPerViewNV = 5261, + ViewportMaskPerViewNV = 5262, + Max = 0x7fffffff, +}; + +enum class SelectionControlShift : unsigned { + Flatten = 0, + DontFlatten = 1, + Max = 0x7fffffff, +}; + +enum class SelectionControlMask : unsigned { + MaskNone = 0, + Flatten = 0x00000001, + DontFlatten = 0x00000002, +}; + +enum class LoopControlShift : unsigned { + Unroll = 0, + DontUnroll = 1, + DependencyInfinite = 2, + DependencyLength = 3, + Max = 0x7fffffff, +}; + +enum class LoopControlMask : unsigned { + MaskNone = 0, + Unroll = 0x00000001, + DontUnroll = 0x00000002, + DependencyInfinite = 0x00000004, + DependencyLength = 0x00000008, +}; + +enum class FunctionControlShift : unsigned { + Inline = 0, + DontInline = 1, + Pure = 2, + Const = 3, + Max = 0x7fffffff, +}; + +enum class FunctionControlMask : unsigned { + MaskNone = 0, + Inline = 0x00000001, + DontInline = 0x00000002, + Pure = 0x00000004, + Const = 0x00000008, +}; + +enum class MemorySemanticsShift : unsigned { + Acquire = 1, + Release = 2, + AcquireRelease = 3, + SequentiallyConsistent = 4, + UniformMemory = 6, + SubgroupMemory = 7, + WorkgroupMemory = 8, + CrossWorkgroupMemory = 9, + AtomicCounterMemory = 10, + ImageMemory = 11, + Max = 0x7fffffff, +}; + +enum class MemorySemanticsMask : unsigned { + MaskNone = 0, + Acquire = 0x00000002, + Release = 0x00000004, + AcquireRelease = 0x00000008, + SequentiallyConsistent = 0x00000010, + UniformMemory = 0x00000040, + SubgroupMemory = 0x00000080, + WorkgroupMemory = 0x00000100, + CrossWorkgroupMemory = 0x00000200, + AtomicCounterMemory = 0x00000400, + ImageMemory = 0x00000800, +}; + +enum class MemoryAccessShift : unsigned { + Volatile = 0, + Aligned = 1, + Nontemporal = 2, + Max = 0x7fffffff, +}; + +enum class MemoryAccessMask : unsigned { + MaskNone = 0, + Volatile = 0x00000001, + Aligned = 0x00000002, + Nontemporal = 0x00000004, +}; + +enum class Scope : unsigned { + CrossDevice = 0, + Device = 1, + Workgroup = 2, + Subgroup = 3, + Invocation = 4, + Max = 0x7fffffff, +}; + +enum class GroupOperation : unsigned { + Reduce = 0, + InclusiveScan = 1, + ExclusiveScan = 2, + Max = 0x7fffffff, +}; + +enum class KernelEnqueueFlags : unsigned { + NoWait = 0, + WaitKernel = 1, + WaitWorkGroup = 2, + Max = 0x7fffffff, +}; + +enum class KernelProfilingInfoShift : unsigned { + CmdExecTime = 0, + Max = 0x7fffffff, +}; + +enum class KernelProfilingInfoMask : unsigned { + MaskNone = 0, + CmdExecTime = 0x00000001, +}; + +enum class Capability : unsigned { + Matrix = 0, + Shader = 1, + Geometry = 2, + Tessellation = 3, + Addresses = 4, + Linkage = 5, + Kernel = 6, + Vector16 = 7, + Float16Buffer = 8, + Float16 = 9, + Float64 = 10, + Int64 = 11, + Int64Atomics = 12, + ImageBasic = 13, + ImageReadWrite = 14, + ImageMipmap = 15, + Pipes = 17, + Groups = 18, + DeviceEnqueue = 19, + LiteralSampler = 20, + AtomicStorage = 21, + Int16 = 22, + TessellationPointSize = 23, + GeometryPointSize = 24, + ImageGatherExtended = 25, + StorageImageMultisample = 27, + UniformBufferArrayDynamicIndexing = 28, + SampledImageArrayDynamicIndexing = 29, + StorageBufferArrayDynamicIndexing = 30, + StorageImageArrayDynamicIndexing = 31, + ClipDistance = 32, + CullDistance = 33, + ImageCubeArray = 34, + SampleRateShading = 35, + ImageRect = 36, + SampledRect = 37, + GenericPointer = 38, + Int8 = 39, + InputAttachment = 40, + SparseResidency = 41, + MinLod = 42, + Sampled1D = 43, + Image1D = 44, + SampledCubeArray = 45, + SampledBuffer = 46, + ImageBuffer = 47, + ImageMSArray = 48, + StorageImageExtendedFormats = 49, + ImageQuery = 50, + DerivativeControl = 51, + InterpolationFunction = 52, + TransformFeedback = 53, + GeometryStreams = 54, + StorageImageReadWithoutFormat = 55, + StorageImageWriteWithoutFormat = 56, + MultiViewport = 57, + SubgroupDispatch = 58, + NamedBarrier = 59, + PipeStorage = 60, + SubgroupBallotKHR = 4423, + DrawParameters = 4427, + SubgroupVoteKHR = 4431, + StorageBuffer16BitAccess = 4433, + StorageUniformBufferBlock16 = 4433, + StorageUniform16 = 4434, + UniformAndStorageBuffer16BitAccess = 4434, + StoragePushConstant16 = 4435, + StorageInputOutput16 = 4436, + DeviceGroup = 4437, + MultiView = 4439, + VariablePointersStorageBuffer = 4441, + VariablePointers = 4442, + AtomicStorageOps = 4445, + SampleMaskPostDepthCoverage = 4447, + ImageGatherBiasLodAMD = 5009, + FragmentMaskAMD = 5010, + StencilExportEXT = 5013, + ImageReadWriteLodAMD = 5015, + SampleMaskOverrideCoverageNV = 5249, + GeometryShaderPassthroughNV = 5251, + ShaderViewportIndexLayerEXT = 5254, + ShaderViewportIndexLayerNV = 5254, + ShaderViewportMaskNV = 5255, + ShaderStereoViewNV = 5259, + PerViewAttributesNV = 5260, + SubgroupShuffleINTEL = 5568, + SubgroupBufferBlockIOINTEL = 5569, + SubgroupImageBlockIOINTEL = 5570, + Max = 0x7fffffff, +}; + +enum class Op : unsigned { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + Max = 0x7fffffff, +}; + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/ext/vulkan/spirv.json b/ext/vulkan/spirv.json index a966cfbc10..988d7bf3ad 100644 --- a/ext/vulkan/spirv.json +++ b/ext/vulkan/spirv.json @@ -1,990 +1,1035 @@ -{ - "spv": - { - "meta": - { - "Comment": - [ - [ - "Copyright (c) 2014-2017 The Khronos Group Inc.", - "", - "Permission is hereby granted, free of charge, to any person obtaining a copy", - "of this software and/or associated documentation files (the \"Materials\"),", - "to deal in the Materials without restriction, including without limitation", - "the rights to use, copy, modify, merge, publish, distribute, sublicense,", - "and/or sell copies of the Materials, and to permit persons to whom the", - "Materials are furnished to do so, subject to the following conditions:", - "", - "The above copyright notice and this permission notice shall be included in", - "all copies or substantial portions of the Materials.", - "", - "MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS", - "STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND", - "HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ ", - "", - "THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS", - "OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", - "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL", - "THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", - "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING", - "FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS", - "IN THE MATERIALS." - ], - [ - "This header is automatically generated by the same tool that creates", - "the Binary Section of the SPIR-V specification." - ], - [ - "Enumeration tokens for SPIR-V, in various styles:", - " C, C++, C++11, JSON, Lua, Python", - "", - "- C will have tokens with a \"Spv\" prefix, e.g.: SpvSourceLanguageGLSL", - "- C++ will have tokens in the \"spv\" name space, e.g.: spv::SourceLanguageGLSL", - "- C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL", - "- Lua will use tables, e.g.: spv.SourceLanguage.GLSL", - "- Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']", - "", - "Some tokens act like mask values, which can be OR'd together,", - "while others are mutually exclusive. The mask-like ones have", - "\"Mask\" in their name, and a parallel enum that has the shift", - "amount (1 << x) for each corresponding enumerant." - ] - ], - "MagicNumber": 119734787, - "Version": 65792, - "Revision": 6, - "OpCodeMask": 65535, - "WordCountShift": 16 - }, - "enum": - [ - { - "Name": "SourceLanguage", - "Type": "Value", - "Values": - { - "Unknown": 0, - "ESSL": 1, - "GLSL": 2, - "OpenCL_C": 3, - "OpenCL_CPP": 4 - } - }, - { - "Name": "ExecutionModel", - "Type": "Value", - "Values": - { - "Vertex": 0, - "TessellationControl": 1, - "TessellationEvaluation": 2, - "Geometry": 3, - "Fragment": 4, - "GLCompute": 5, - "Kernel": 6 - } - }, - { - "Name": "AddressingModel", - "Type": "Value", - "Values": - { - "Logical": 0, - "Physical32": 1, - "Physical64": 2 - } - }, - { - "Name": "MemoryModel", - "Type": "Value", - "Values": - { - "Simple": 0, - "GLSL450": 1, - "OpenCL": 2 - } - }, - { - "Name": "ExecutionMode", - "Type": "Value", - "Values": - { - "Invocations": 0, - "SpacingEqual": 1, - "SpacingFractionalEven": 2, - "SpacingFractionalOdd": 3, - "VertexOrderCw": 4, - "VertexOrderCcw": 5, - "PixelCenterInteger": 6, - "OriginUpperLeft": 7, - "OriginLowerLeft": 8, - "EarlyFragmentTests": 9, - "PointMode": 10, - "Xfb": 11, - "DepthReplacing": 12, - "DepthGreater": 14, - "DepthLess": 15, - "DepthUnchanged": 16, - "LocalSize": 17, - "LocalSizeHint": 18, - "InputPoints": 19, - "InputLines": 20, - "InputLinesAdjacency": 21, - "Triangles": 22, - "InputTrianglesAdjacency": 23, - "Quads": 24, - "Isolines": 25, - "OutputVertices": 26, - "OutputPoints": 27, - "OutputLineStrip": 28, - "OutputTriangleStrip": 29, - "VecTypeHint": 30, - "ContractionOff": 31, - "Initializer": 33, - "Finalizer": 34, - "SubgroupSize": 35, - "SubgroupsPerWorkgroup": 36 - } - }, - { - "Name": "StorageClass", - "Type": "Value", - "Values": - { - "UniformConstant": 0, - "Input": 1, - "Uniform": 2, - "Output": 3, - "Workgroup": 4, - "CrossWorkgroup": 5, - "Private": 6, - "Function": 7, - "Generic": 8, - "PushConstant": 9, - "AtomicCounter": 10, - "Image": 11 - } - }, - { - "Name": "Dim", - "Type": "Value", - "Values": - { - "Dim1D": 0, - "Dim2D": 1, - "Dim3D": 2, - "Cube": 3, - "Rect": 4, - "Buffer": 5, - "SubpassData": 6 - } - }, - { - "Name": "SamplerAddressingMode", - "Type": "Value", - "Values": - { - "None": 0, - "ClampToEdge": 1, - "Clamp": 2, - "Repeat": 3, - "RepeatMirrored": 4 - } - }, - { - "Name": "SamplerFilterMode", - "Type": "Value", - "Values": - { - "Nearest": 0, - "Linear": 1 - } - }, - { - "Name": "ImageFormat", - "Type": "Value", - "Values": - { - "Unknown": 0, - "Rgba32f": 1, - "Rgba16f": 2, - "R32f": 3, - "Rgba8": 4, - "Rgba8Snorm": 5, - "Rg32f": 6, - "Rg16f": 7, - "R11fG11fB10f": 8, - "R16f": 9, - "Rgba16": 10, - "Rgb10A2": 11, - "Rg16": 12, - "Rg8": 13, - "R16": 14, - "R8": 15, - "Rgba16Snorm": 16, - "Rg16Snorm": 17, - "Rg8Snorm": 18, - "R16Snorm": 19, - "R8Snorm": 20, - "Rgba32i": 21, - "Rgba16i": 22, - "Rgba8i": 23, - "R32i": 24, - "Rg32i": 25, - "Rg16i": 26, - "Rg8i": 27, - "R16i": 28, - "R8i": 29, - "Rgba32ui": 30, - "Rgba16ui": 31, - "Rgba8ui": 32, - "R32ui": 33, - "Rgb10a2ui": 34, - "Rg32ui": 35, - "Rg16ui": 36, - "Rg8ui": 37, - "R16ui": 38, - "R8ui": 39 - } - }, - { - "Name": "ImageChannelOrder", - "Type": "Value", - "Values": - { - "R": 0, - "A": 1, - "RG": 2, - "RA": 3, - "RGB": 4, - "RGBA": 5, - "BGRA": 6, - "ARGB": 7, - "Intensity": 8, - "Luminance": 9, - "Rx": 10, - "RGx": 11, - "RGBx": 12, - "Depth": 13, - "DepthStencil": 14, - "sRGB": 15, - "sRGBx": 16, - "sRGBA": 17, - "sBGRA": 18, - "ABGR": 19 - } - }, - { - "Name": "ImageChannelDataType", - "Type": "Value", - "Values": - { - "SnormInt8": 0, - "SnormInt16": 1, - "UnormInt8": 2, - "UnormInt16": 3, - "UnormShort565": 4, - "UnormShort555": 5, - "UnormInt101010": 6, - "SignedInt8": 7, - "SignedInt16": 8, - "SignedInt32": 9, - "UnsignedInt8": 10, - "UnsignedInt16": 11, - "UnsignedInt32": 12, - "HalfFloat": 13, - "Float": 14, - "UnormInt24": 15, - "UnormInt101010_2": 16 - } - }, - { - "Name": "ImageOperands", - "Type": "Bit", - "Values": - { - "Bias": 0, - "Lod": 1, - "Grad": 2, - "ConstOffset": 3, - "Offset": 4, - "ConstOffsets": 5, - "Sample": 6, - "MinLod": 7 - } - }, - { - "Name": "FPFastMathMode", - "Type": "Bit", - "Values": - { - "NotNaN": 0, - "NotInf": 1, - "NSZ": 2, - "AllowRecip": 3, - "Fast": 4 - } - }, - { - "Name": "FPRoundingMode", - "Type": "Value", - "Values": - { - "RTE": 0, - "RTZ": 1, - "RTP": 2, - "RTN": 3 - } - }, - { - "Name": "LinkageType", - "Type": "Value", - "Values": - { - "Export": 0, - "Import": 1 - } - }, - { - "Name": "AccessQualifier", - "Type": "Value", - "Values": - { - "ReadOnly": 0, - "WriteOnly": 1, - "ReadWrite": 2 - } - }, - { - "Name": "FunctionParameterAttribute", - "Type": "Value", - "Values": - { - "Zext": 0, - "Sext": 1, - "ByVal": 2, - "Sret": 3, - "NoAlias": 4, - "NoCapture": 5, - "NoWrite": 6, - "NoReadWrite": 7 - } - }, - { - "Name": "Decoration", - "Type": "Value", - "Values": - { - "RelaxedPrecision": 0, - "SpecId": 1, - "Block": 2, - "BufferBlock": 3, - "RowMajor": 4, - "ColMajor": 5, - "ArrayStride": 6, - "MatrixStride": 7, - "GLSLShared": 8, - "GLSLPacked": 9, - "CPacked": 10, - "BuiltIn": 11, - "NoPerspective": 13, - "Flat": 14, - "Patch": 15, - "Centroid": 16, - "Sample": 17, - "Invariant": 18, - "Restrict": 19, - "Aliased": 20, - "Volatile": 21, - "Constant": 22, - "Coherent": 23, - "NonWritable": 24, - "NonReadable": 25, - "Uniform": 26, - "SaturatedConversion": 28, - "Stream": 29, - "Location": 30, - "Component": 31, - "Index": 32, - "Binding": 33, - "DescriptorSet": 34, - "Offset": 35, - "XfbBuffer": 36, - "XfbStride": 37, - "FuncParamAttr": 38, - "FPRoundingMode": 39, - "FPFastMathMode": 40, - "LinkageAttributes": 41, - "NoContraction": 42, - "InputAttachmentIndex": 43, - "Alignment": 44, - "MaxByteOffset": 45, - "OverrideCoverageNV": 5248, - "PassthroughNV": 5250, - "ViewportRelativeNV": 5252, - "SecondaryViewportRelativeNV": 5256 - } - }, - { - "Name": "BuiltIn", - "Type": "Value", - "Values": - { - "Position": 0, - "PointSize": 1, - "ClipDistance": 3, - "CullDistance": 4, - "VertexId": 5, - "InstanceId": 6, - "PrimitiveId": 7, - "InvocationId": 8, - "Layer": 9, - "ViewportIndex": 10, - "TessLevelOuter": 11, - "TessLevelInner": 12, - "TessCoord": 13, - "PatchVertices": 14, - "FragCoord": 15, - "PointCoord": 16, - "FrontFacing": 17, - "SampleId": 18, - "SamplePosition": 19, - "SampleMask": 20, - "FragDepth": 22, - "HelperInvocation": 23, - "NumWorkgroups": 24, - "WorkgroupSize": 25, - "WorkgroupId": 26, - "LocalInvocationId": 27, - "GlobalInvocationId": 28, - "LocalInvocationIndex": 29, - "WorkDim": 30, - "GlobalSize": 31, - "EnqueuedWorkgroupSize": 32, - "GlobalOffset": 33, - "GlobalLinearId": 34, - "SubgroupSize": 36, - "SubgroupMaxSize": 37, - "NumSubgroups": 38, - "NumEnqueuedSubgroups": 39, - "SubgroupId": 40, - "SubgroupLocalInvocationId": 41, - "VertexIndex": 42, - "InstanceIndex": 43, - "SubgroupEqMaskKHR": 4416, - "SubgroupGeMaskKHR": 4417, - "SubgroupGtMaskKHR": 4418, - "SubgroupLeMaskKHR": 4419, - "SubgroupLtMaskKHR": 4420, - "BaseVertex": 4424, - "BaseInstance": 4425, - "DrawIndex": 4426, - "DeviceIndex": 4438, - "ViewIndex": 4440, - "ViewportMaskNV": 5253, - "SecondaryPositionNV": 5257, - "SecondaryViewportMaskNV": 5258, - "PositionPerViewNV": 5261, - "ViewportMaskPerViewNV": 5262 - } - }, - { - "Name": "SelectionControl", - "Type": "Bit", - "Values": - { - "Flatten": 0, - "DontFlatten": 1 - } - }, - { - "Name": "LoopControl", - "Type": "Bit", - "Values": - { - "Unroll": 0, - "DontUnroll": 1, - "DependencyInfinite": 2, - "DependencyLength": 3 - } - }, - { - "Name": "FunctionControl", - "Type": "Bit", - "Values": - { - "Inline": 0, - "DontInline": 1, - "Pure": 2, - "Const": 3 - } - }, - { - "Name": "MemorySemantics", - "Type": "Bit", - "Values": - { - "Acquire": 1, - "Release": 2, - "AcquireRelease": 3, - "SequentiallyConsistent": 4, - "UniformMemory": 6, - "SubgroupMemory": 7, - "WorkgroupMemory": 8, - "CrossWorkgroupMemory": 9, - "AtomicCounterMemory": 10, - "ImageMemory": 11 - } - }, - { - "Name": "MemoryAccess", - "Type": "Bit", - "Values": - { - "Volatile": 0, - "Aligned": 1, - "Nontemporal": 2 - } - }, - { - "Name": "Scope", - "Type": "Value", - "Values": - { - "CrossDevice": 0, - "Device": 1, - "Workgroup": 2, - "Subgroup": 3, - "Invocation": 4 - } - }, - { - "Name": "GroupOperation", - "Type": "Value", - "Values": - { - "Reduce": 0, - "InclusiveScan": 1, - "ExclusiveScan": 2 - } - }, - { - "Name": "KernelEnqueueFlags", - "Type": "Value", - "Values": - { - "NoWait": 0, - "WaitKernel": 1, - "WaitWorkGroup": 2 - } - }, - { - "Name": "KernelProfilingInfo", - "Type": "Bit", - "Values": - { - "CmdExecTime": 0 - } - }, - { - "Name": "Capability", - "Type": "Value", - "Values": - { - "Matrix": 0, - "Shader": 1, - "Geometry": 2, - "Tessellation": 3, - "Addresses": 4, - "Linkage": 5, - "Kernel": 6, - "Vector16": 7, - "Float16Buffer": 8, - "Float16": 9, - "Float64": 10, - "Int64": 11, - "Int64Atomics": 12, - "ImageBasic": 13, - "ImageReadWrite": 14, - "ImageMipmap": 15, - "Pipes": 17, - "Groups": 18, - "DeviceEnqueue": 19, - "LiteralSampler": 20, - "AtomicStorage": 21, - "Int16": 22, - "TessellationPointSize": 23, - "GeometryPointSize": 24, - "ImageGatherExtended": 25, - "StorageImageMultisample": 27, - "UniformBufferArrayDynamicIndexing": 28, - "SampledImageArrayDynamicIndexing": 29, - "StorageBufferArrayDynamicIndexing": 30, - "StorageImageArrayDynamicIndexing": 31, - "ClipDistance": 32, - "CullDistance": 33, - "ImageCubeArray": 34, - "SampleRateShading": 35, - "ImageRect": 36, - "SampledRect": 37, - "GenericPointer": 38, - "Int8": 39, - "InputAttachment": 40, - "SparseResidency": 41, - "MinLod": 42, - "Sampled1D": 43, - "Image1D": 44, - "SampledCubeArray": 45, - "SampledBuffer": 46, - "ImageBuffer": 47, - "ImageMSArray": 48, - "StorageImageExtendedFormats": 49, - "ImageQuery": 50, - "DerivativeControl": 51, - "InterpolationFunction": 52, - "TransformFeedback": 53, - "GeometryStreams": 54, - "StorageImageReadWithoutFormat": 55, - "StorageImageWriteWithoutFormat": 56, - "MultiViewport": 57, - "SubgroupDispatch": 58, - "NamedBarrier": 59, - "PipeStorage": 60, - "SubgroupBallotKHR": 4423, - "DrawParameters": 4427, - "SubgroupVoteKHR": 4431, - "StorageUniformBufferBlock16": 4433, - "StorageUniform16": 4434, - "StoragePushConstant16": 4435, - "StorageInputOutput16": 4436, - "DeviceGroup": 4437, - "MultiView": 4439, - "SampleMaskOverrideCoverageNV": 5249, - "GeometryShaderPassthroughNV": 5251, - "ShaderViewportIndexLayerNV": 5254, - "ShaderViewportMaskNV": 5255, - "ShaderStereoViewNV": 5259, - "PerViewAttributesNV": 5260 - } - }, - { - "Name": "Op", - "Type": "Value", - "Values": - { - "OpNop": 0, - "OpUndef": 1, - "OpSourceContinued": 2, - "OpSource": 3, - "OpSourceExtension": 4, - "OpName": 5, - "OpMemberName": 6, - "OpString": 7, - "OpLine": 8, - "OpExtension": 10, - "OpExtInstImport": 11, - "OpExtInst": 12, - "OpMemoryModel": 14, - "OpEntryPoint": 15, - "OpExecutionMode": 16, - "OpCapability": 17, - "OpTypeVoid": 19, - "OpTypeBool": 20, - "OpTypeInt": 21, - "OpTypeFloat": 22, - "OpTypeVector": 23, - "OpTypeMatrix": 24, - "OpTypeImage": 25, - "OpTypeSampler": 26, - "OpTypeSampledImage": 27, - "OpTypeArray": 28, - "OpTypeRuntimeArray": 29, - "OpTypeStruct": 30, - "OpTypeOpaque": 31, - "OpTypePointer": 32, - "OpTypeFunction": 33, - "OpTypeEvent": 34, - "OpTypeDeviceEvent": 35, - "OpTypeReserveId": 36, - "OpTypeQueue": 37, - "OpTypePipe": 38, - "OpTypeForwardPointer": 39, - "OpConstantTrue": 41, - "OpConstantFalse": 42, - "OpConstant": 43, - "OpConstantComposite": 44, - "OpConstantSampler": 45, - "OpConstantNull": 46, - "OpSpecConstantTrue": 48, - "OpSpecConstantFalse": 49, - "OpSpecConstant": 50, - "OpSpecConstantComposite": 51, - "OpSpecConstantOp": 52, - "OpFunction": 54, - "OpFunctionParameter": 55, - "OpFunctionEnd": 56, - "OpFunctionCall": 57, - "OpVariable": 59, - "OpImageTexelPointer": 60, - "OpLoad": 61, - "OpStore": 62, - "OpCopyMemory": 63, - "OpCopyMemorySized": 64, - "OpAccessChain": 65, - "OpInBoundsAccessChain": 66, - "OpPtrAccessChain": 67, - "OpArrayLength": 68, - "OpGenericPtrMemSemantics": 69, - "OpInBoundsPtrAccessChain": 70, - "OpDecorate": 71, - "OpMemberDecorate": 72, - "OpDecorationGroup": 73, - "OpGroupDecorate": 74, - "OpGroupMemberDecorate": 75, - "OpVectorExtractDynamic": 77, - "OpVectorInsertDynamic": 78, - "OpVectorShuffle": 79, - "OpCompositeConstruct": 80, - "OpCompositeExtract": 81, - "OpCompositeInsert": 82, - "OpCopyObject": 83, - "OpTranspose": 84, - "OpSampledImage": 86, - "OpImageSampleImplicitLod": 87, - "OpImageSampleExplicitLod": 88, - "OpImageSampleDrefImplicitLod": 89, - "OpImageSampleDrefExplicitLod": 90, - "OpImageSampleProjImplicitLod": 91, - "OpImageSampleProjExplicitLod": 92, - "OpImageSampleProjDrefImplicitLod": 93, - "OpImageSampleProjDrefExplicitLod": 94, - "OpImageFetch": 95, - "OpImageGather": 96, - "OpImageDrefGather": 97, - "OpImageRead": 98, - "OpImageWrite": 99, - "OpImage": 100, - "OpImageQueryFormat": 101, - "OpImageQueryOrder": 102, - "OpImageQuerySizeLod": 103, - "OpImageQuerySize": 104, - "OpImageQueryLod": 105, - "OpImageQueryLevels": 106, - "OpImageQuerySamples": 107, - "OpConvertFToU": 109, - "OpConvertFToS": 110, - "OpConvertSToF": 111, - "OpConvertUToF": 112, - "OpUConvert": 113, - "OpSConvert": 114, - "OpFConvert": 115, - "OpQuantizeToF16": 116, - "OpConvertPtrToU": 117, - "OpSatConvertSToU": 118, - "OpSatConvertUToS": 119, - "OpConvertUToPtr": 120, - "OpPtrCastToGeneric": 121, - "OpGenericCastToPtr": 122, - "OpGenericCastToPtrExplicit": 123, - "OpBitcast": 124, - "OpSNegate": 126, - "OpFNegate": 127, - "OpIAdd": 128, - "OpFAdd": 129, - "OpISub": 130, - "OpFSub": 131, - "OpIMul": 132, - "OpFMul": 133, - "OpUDiv": 134, - "OpSDiv": 135, - "OpFDiv": 136, - "OpUMod": 137, - "OpSRem": 138, - "OpSMod": 139, - "OpFRem": 140, - "OpFMod": 141, - "OpVectorTimesScalar": 142, - "OpMatrixTimesScalar": 143, - "OpVectorTimesMatrix": 144, - "OpMatrixTimesVector": 145, - "OpMatrixTimesMatrix": 146, - "OpOuterProduct": 147, - "OpDot": 148, - "OpIAddCarry": 149, - "OpISubBorrow": 150, - "OpUMulExtended": 151, - "OpSMulExtended": 152, - "OpAny": 154, - "OpAll": 155, - "OpIsNan": 156, - "OpIsInf": 157, - "OpIsFinite": 158, - "OpIsNormal": 159, - "OpSignBitSet": 160, - "OpLessOrGreater": 161, - "OpOrdered": 162, - "OpUnordered": 163, - "OpLogicalEqual": 164, - "OpLogicalNotEqual": 165, - "OpLogicalOr": 166, - "OpLogicalAnd": 167, - "OpLogicalNot": 168, - "OpSelect": 169, - "OpIEqual": 170, - "OpINotEqual": 171, - "OpUGreaterThan": 172, - "OpSGreaterThan": 173, - "OpUGreaterThanEqual": 174, - "OpSGreaterThanEqual": 175, - "OpULessThan": 176, - "OpSLessThan": 177, - "OpULessThanEqual": 178, - "OpSLessThanEqual": 179, - "OpFOrdEqual": 180, - "OpFUnordEqual": 181, - "OpFOrdNotEqual": 182, - "OpFUnordNotEqual": 183, - "OpFOrdLessThan": 184, - "OpFUnordLessThan": 185, - "OpFOrdGreaterThan": 186, - "OpFUnordGreaterThan": 187, - "OpFOrdLessThanEqual": 188, - "OpFUnordLessThanEqual": 189, - "OpFOrdGreaterThanEqual": 190, - "OpFUnordGreaterThanEqual": 191, - "OpShiftRightLogical": 194, - "OpShiftRightArithmetic": 195, - "OpShiftLeftLogical": 196, - "OpBitwiseOr": 197, - "OpBitwiseXor": 198, - "OpBitwiseAnd": 199, - "OpNot": 200, - "OpBitFieldInsert": 201, - "OpBitFieldSExtract": 202, - "OpBitFieldUExtract": 203, - "OpBitReverse": 204, - "OpBitCount": 205, - "OpDPdx": 207, - "OpDPdy": 208, - "OpFwidth": 209, - "OpDPdxFine": 210, - "OpDPdyFine": 211, - "OpFwidthFine": 212, - "OpDPdxCoarse": 213, - "OpDPdyCoarse": 214, - "OpFwidthCoarse": 215, - "OpEmitVertex": 218, - "OpEndPrimitive": 219, - "OpEmitStreamVertex": 220, - "OpEndStreamPrimitive": 221, - "OpControlBarrier": 224, - "OpMemoryBarrier": 225, - "OpAtomicLoad": 227, - "OpAtomicStore": 228, - "OpAtomicExchange": 229, - "OpAtomicCompareExchange": 230, - "OpAtomicCompareExchangeWeak": 231, - "OpAtomicIIncrement": 232, - "OpAtomicIDecrement": 233, - "OpAtomicIAdd": 234, - "OpAtomicISub": 235, - "OpAtomicSMin": 236, - "OpAtomicUMin": 237, - "OpAtomicSMax": 238, - "OpAtomicUMax": 239, - "OpAtomicAnd": 240, - "OpAtomicOr": 241, - "OpAtomicXor": 242, - "OpPhi": 245, - "OpLoopMerge": 246, - "OpSelectionMerge": 247, - "OpLabel": 248, - "OpBranch": 249, - "OpBranchConditional": 250, - "OpSwitch": 251, - "OpKill": 252, - "OpReturn": 253, - "OpReturnValue": 254, - "OpUnreachable": 255, - "OpLifetimeStart": 256, - "OpLifetimeStop": 257, - "OpGroupAsyncCopy": 259, - "OpGroupWaitEvents": 260, - "OpGroupAll": 261, - "OpGroupAny": 262, - "OpGroupBroadcast": 263, - "OpGroupIAdd": 264, - "OpGroupFAdd": 265, - "OpGroupFMin": 266, - "OpGroupUMin": 267, - "OpGroupSMin": 268, - "OpGroupFMax": 269, - "OpGroupUMax": 270, - "OpGroupSMax": 271, - "OpReadPipe": 274, - "OpWritePipe": 275, - "OpReservedReadPipe": 276, - "OpReservedWritePipe": 277, - "OpReserveReadPipePackets": 278, - "OpReserveWritePipePackets": 279, - "OpCommitReadPipe": 280, - "OpCommitWritePipe": 281, - "OpIsValidReserveId": 282, - "OpGetNumPipePackets": 283, - "OpGetMaxPipePackets": 284, - "OpGroupReserveReadPipePackets": 285, - "OpGroupReserveWritePipePackets": 286, - "OpGroupCommitReadPipe": 287, - "OpGroupCommitWritePipe": 288, - "OpEnqueueMarker": 291, - "OpEnqueueKernel": 292, - "OpGetKernelNDrangeSubGroupCount": 293, - "OpGetKernelNDrangeMaxSubGroupSize": 294, - "OpGetKernelWorkGroupSize": 295, - "OpGetKernelPreferredWorkGroupSizeMultiple": 296, - "OpRetainEvent": 297, - "OpReleaseEvent": 298, - "OpCreateUserEvent": 299, - "OpIsValidEvent": 300, - "OpSetUserEventStatus": 301, - "OpCaptureEventProfilingInfo": 302, - "OpGetDefaultQueue": 303, - "OpBuildNDRange": 304, - "OpImageSparseSampleImplicitLod": 305, - "OpImageSparseSampleExplicitLod": 306, - "OpImageSparseSampleDrefImplicitLod": 307, - "OpImageSparseSampleDrefExplicitLod": 308, - "OpImageSparseSampleProjImplicitLod": 309, - "OpImageSparseSampleProjExplicitLod": 310, - "OpImageSparseSampleProjDrefImplicitLod": 311, - "OpImageSparseSampleProjDrefExplicitLod": 312, - "OpImageSparseFetch": 313, - "OpImageSparseGather": 314, - "OpImageSparseDrefGather": 315, - "OpImageSparseTexelsResident": 316, - "OpNoLine": 317, - "OpAtomicFlagTestAndSet": 318, - "OpAtomicFlagClear": 319, - "OpImageSparseRead": 320, - "OpSizeOf": 321, - "OpTypePipeStorage": 322, - "OpConstantPipeStorage": 323, - "OpCreatePipeFromPipeStorage": 324, - "OpGetKernelLocalSizeForSubgroupCount": 325, - "OpGetKernelMaxNumSubgroups": 326, - "OpTypeNamedBarrier": 327, - "OpNamedBarrierInitialize": 328, - "OpMemoryNamedBarrier": 329, - "OpModuleProcessed": 330, - "OpSubgroupBallotKHR": 4421, - "OpSubgroupFirstInvocationKHR": 4422, - "OpSubgroupAllKHR": 4428, - "OpSubgroupAnyKHR": 4429, - "OpSubgroupAllEqualKHR": 4430, - "OpSubgroupReadInvocationKHR": 4432 - } - } - ] - } -} - +{ + "spv": + { + "meta": + { + "Comment": + [ + [ + "Copyright (c) 2014-2017 The Khronos Group Inc.", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy", + "of this software and/or associated documentation files (the \"Materials\"),", + "to deal in the Materials without restriction, including without limitation", + "the rights to use, copy, modify, merge, publish, distribute, sublicense,", + "and/or sell copies of the Materials, and to permit persons to whom the", + "Materials are furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in", + "all copies or substantial portions of the Materials.", + "", + "MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS", + "STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND", + "HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ ", + "", + "THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS", + "OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL", + "THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING", + "FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS", + "IN THE MATERIALS." + ], + [ + "This header is automatically generated by the same tool that creates", + "the Binary Section of the SPIR-V specification." + ], + [ + "Enumeration tokens for SPIR-V, in various styles:", + " C, C++, C++11, JSON, Lua, Python", + "", + "- C will have tokens with a \"Spv\" prefix, e.g.: SpvSourceLanguageGLSL", + "- C++ will have tokens in the \"spv\" name space, e.g.: spv::SourceLanguageGLSL", + "- C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL", + "- Lua will use tables, e.g.: spv.SourceLanguage.GLSL", + "- Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']", + "", + "Some tokens act like mask values, which can be OR'd together,", + "while others are mutually exclusive. The mask-like ones have", + "\"Mask\" in their name, and a parallel enum that has the shift", + "amount (1 << x) for each corresponding enumerant." + ] + ], + "MagicNumber": 119734787, + "Version": 65792, + "Revision": 8, + "OpCodeMask": 65535, + "WordCountShift": 16 + }, + "enum": + [ + { + "Name": "SourceLanguage", + "Type": "Value", + "Values": + { + "Unknown": 0, + "ESSL": 1, + "GLSL": 2, + "OpenCL_C": 3, + "OpenCL_CPP": 4, + "HLSL": 5 + } + }, + { + "Name": "ExecutionModel", + "Type": "Value", + "Values": + { + "Vertex": 0, + "TessellationControl": 1, + "TessellationEvaluation": 2, + "Geometry": 3, + "Fragment": 4, + "GLCompute": 5, + "Kernel": 6 + } + }, + { + "Name": "AddressingModel", + "Type": "Value", + "Values": + { + "Logical": 0, + "Physical32": 1, + "Physical64": 2 + } + }, + { + "Name": "MemoryModel", + "Type": "Value", + "Values": + { + "Simple": 0, + "GLSL450": 1, + "OpenCL": 2 + } + }, + { + "Name": "ExecutionMode", + "Type": "Value", + "Values": + { + "Invocations": 0, + "SpacingEqual": 1, + "SpacingFractionalEven": 2, + "SpacingFractionalOdd": 3, + "VertexOrderCw": 4, + "VertexOrderCcw": 5, + "PixelCenterInteger": 6, + "OriginUpperLeft": 7, + "OriginLowerLeft": 8, + "EarlyFragmentTests": 9, + "PointMode": 10, + "Xfb": 11, + "DepthReplacing": 12, + "DepthGreater": 14, + "DepthLess": 15, + "DepthUnchanged": 16, + "LocalSize": 17, + "LocalSizeHint": 18, + "InputPoints": 19, + "InputLines": 20, + "InputLinesAdjacency": 21, + "Triangles": 22, + "InputTrianglesAdjacency": 23, + "Quads": 24, + "Isolines": 25, + "OutputVertices": 26, + "OutputPoints": 27, + "OutputLineStrip": 28, + "OutputTriangleStrip": 29, + "VecTypeHint": 30, + "ContractionOff": 31, + "Initializer": 33, + "Finalizer": 34, + "SubgroupSize": 35, + "SubgroupsPerWorkgroup": 36, + "PostDepthCoverage": 4446, + "StencilRefReplacingEXT": 5027 + } + }, + { + "Name": "StorageClass", + "Type": "Value", + "Values": + { + "UniformConstant": 0, + "Input": 1, + "Uniform": 2, + "Output": 3, + "Workgroup": 4, + "CrossWorkgroup": 5, + "Private": 6, + "Function": 7, + "Generic": 8, + "PushConstant": 9, + "AtomicCounter": 10, + "Image": 11, + "StorageBuffer": 12 + } + }, + { + "Name": "Dim", + "Type": "Value", + "Values": + { + "Dim1D": 0, + "Dim2D": 1, + "Dim3D": 2, + "Cube": 3, + "Rect": 4, + "Buffer": 5, + "SubpassData": 6 + } + }, + { + "Name": "SamplerAddressingMode", + "Type": "Value", + "Values": + { + "None": 0, + "ClampToEdge": 1, + "Clamp": 2, + "Repeat": 3, + "RepeatMirrored": 4 + } + }, + { + "Name": "SamplerFilterMode", + "Type": "Value", + "Values": + { + "Nearest": 0, + "Linear": 1 + } + }, + { + "Name": "ImageFormat", + "Type": "Value", + "Values": + { + "Unknown": 0, + "Rgba32f": 1, + "Rgba16f": 2, + "R32f": 3, + "Rgba8": 4, + "Rgba8Snorm": 5, + "Rg32f": 6, + "Rg16f": 7, + "R11fG11fB10f": 8, + "R16f": 9, + "Rgba16": 10, + "Rgb10A2": 11, + "Rg16": 12, + "Rg8": 13, + "R16": 14, + "R8": 15, + "Rgba16Snorm": 16, + "Rg16Snorm": 17, + "Rg8Snorm": 18, + "R16Snorm": 19, + "R8Snorm": 20, + "Rgba32i": 21, + "Rgba16i": 22, + "Rgba8i": 23, + "R32i": 24, + "Rg32i": 25, + "Rg16i": 26, + "Rg8i": 27, + "R16i": 28, + "R8i": 29, + "Rgba32ui": 30, + "Rgba16ui": 31, + "Rgba8ui": 32, + "R32ui": 33, + "Rgb10a2ui": 34, + "Rg32ui": 35, + "Rg16ui": 36, + "Rg8ui": 37, + "R16ui": 38, + "R8ui": 39 + } + }, + { + "Name": "ImageChannelOrder", + "Type": "Value", + "Values": + { + "R": 0, + "A": 1, + "RG": 2, + "RA": 3, + "RGB": 4, + "RGBA": 5, + "BGRA": 6, + "ARGB": 7, + "Intensity": 8, + "Luminance": 9, + "Rx": 10, + "RGx": 11, + "RGBx": 12, + "Depth": 13, + "DepthStencil": 14, + "sRGB": 15, + "sRGBx": 16, + "sRGBA": 17, + "sBGRA": 18, + "ABGR": 19 + } + }, + { + "Name": "ImageChannelDataType", + "Type": "Value", + "Values": + { + "SnormInt8": 0, + "SnormInt16": 1, + "UnormInt8": 2, + "UnormInt16": 3, + "UnormShort565": 4, + "UnormShort555": 5, + "UnormInt101010": 6, + "SignedInt8": 7, + "SignedInt16": 8, + "SignedInt32": 9, + "UnsignedInt8": 10, + "UnsignedInt16": 11, + "UnsignedInt32": 12, + "HalfFloat": 13, + "Float": 14, + "UnormInt24": 15, + "UnormInt101010_2": 16 + } + }, + { + "Name": "ImageOperands", + "Type": "Bit", + "Values": + { + "Bias": 0, + "Lod": 1, + "Grad": 2, + "ConstOffset": 3, + "Offset": 4, + "ConstOffsets": 5, + "Sample": 6, + "MinLod": 7 + } + }, + { + "Name": "FPFastMathMode", + "Type": "Bit", + "Values": + { + "NotNaN": 0, + "NotInf": 1, + "NSZ": 2, + "AllowRecip": 3, + "Fast": 4 + } + }, + { + "Name": "FPRoundingMode", + "Type": "Value", + "Values": + { + "RTE": 0, + "RTZ": 1, + "RTP": 2, + "RTN": 3 + } + }, + { + "Name": "LinkageType", + "Type": "Value", + "Values": + { + "Export": 0, + "Import": 1 + } + }, + { + "Name": "AccessQualifier", + "Type": "Value", + "Values": + { + "ReadOnly": 0, + "WriteOnly": 1, + "ReadWrite": 2 + } + }, + { + "Name": "FunctionParameterAttribute", + "Type": "Value", + "Values": + { + "Zext": 0, + "Sext": 1, + "ByVal": 2, + "Sret": 3, + "NoAlias": 4, + "NoCapture": 5, + "NoWrite": 6, + "NoReadWrite": 7 + } + }, + { + "Name": "Decoration", + "Type": "Value", + "Values": + { + "RelaxedPrecision": 0, + "SpecId": 1, + "Block": 2, + "BufferBlock": 3, + "RowMajor": 4, + "ColMajor": 5, + "ArrayStride": 6, + "MatrixStride": 7, + "GLSLShared": 8, + "GLSLPacked": 9, + "CPacked": 10, + "BuiltIn": 11, + "NoPerspective": 13, + "Flat": 14, + "Patch": 15, + "Centroid": 16, + "Sample": 17, + "Invariant": 18, + "Restrict": 19, + "Aliased": 20, + "Volatile": 21, + "Constant": 22, + "Coherent": 23, + "NonWritable": 24, + "NonReadable": 25, + "Uniform": 26, + "SaturatedConversion": 28, + "Stream": 29, + "Location": 30, + "Component": 31, + "Index": 32, + "Binding": 33, + "DescriptorSet": 34, + "Offset": 35, + "XfbBuffer": 36, + "XfbStride": 37, + "FuncParamAttr": 38, + "FPRoundingMode": 39, + "FPFastMathMode": 40, + "LinkageAttributes": 41, + "NoContraction": 42, + "InputAttachmentIndex": 43, + "Alignment": 44, + "MaxByteOffset": 45, + "ExplicitInterpAMD": 4999, + "OverrideCoverageNV": 5248, + "PassthroughNV": 5250, + "ViewportRelativeNV": 5252, + "SecondaryViewportRelativeNV": 5256 + } + }, + { + "Name": "BuiltIn", + "Type": "Value", + "Values": + { + "Position": 0, + "PointSize": 1, + "ClipDistance": 3, + "CullDistance": 4, + "VertexId": 5, + "InstanceId": 6, + "PrimitiveId": 7, + "InvocationId": 8, + "Layer": 9, + "ViewportIndex": 10, + "TessLevelOuter": 11, + "TessLevelInner": 12, + "TessCoord": 13, + "PatchVertices": 14, + "FragCoord": 15, + "PointCoord": 16, + "FrontFacing": 17, + "SampleId": 18, + "SamplePosition": 19, + "SampleMask": 20, + "FragDepth": 22, + "HelperInvocation": 23, + "NumWorkgroups": 24, + "WorkgroupSize": 25, + "WorkgroupId": 26, + "LocalInvocationId": 27, + "GlobalInvocationId": 28, + "LocalInvocationIndex": 29, + "WorkDim": 30, + "GlobalSize": 31, + "EnqueuedWorkgroupSize": 32, + "GlobalOffset": 33, + "GlobalLinearId": 34, + "SubgroupSize": 36, + "SubgroupMaxSize": 37, + "NumSubgroups": 38, + "NumEnqueuedSubgroups": 39, + "SubgroupId": 40, + "SubgroupLocalInvocationId": 41, + "VertexIndex": 42, + "InstanceIndex": 43, + "SubgroupEqMaskKHR": 4416, + "SubgroupGeMaskKHR": 4417, + "SubgroupGtMaskKHR": 4418, + "SubgroupLeMaskKHR": 4419, + "SubgroupLtMaskKHR": 4420, + "BaseVertex": 4424, + "BaseInstance": 4425, + "DrawIndex": 4426, + "DeviceIndex": 4438, + "ViewIndex": 4440, + "BaryCoordNoPerspAMD": 4992, + "BaryCoordNoPerspCentroidAMD": 4993, + "BaryCoordNoPerspSampleAMD": 4994, + "BaryCoordSmoothAMD": 4995, + "BaryCoordSmoothCentroidAMD": 4996, + "BaryCoordSmoothSampleAMD": 4997, + "BaryCoordPullModelAMD": 4998, + "FragStencilRefEXT": 5014, + "ViewportMaskNV": 5253, + "SecondaryPositionNV": 5257, + "SecondaryViewportMaskNV": 5258, + "PositionPerViewNV": 5261, + "ViewportMaskPerViewNV": 5262 + } + }, + { + "Name": "SelectionControl", + "Type": "Bit", + "Values": + { + "Flatten": 0, + "DontFlatten": 1 + } + }, + { + "Name": "LoopControl", + "Type": "Bit", + "Values": + { + "Unroll": 0, + "DontUnroll": 1, + "DependencyInfinite": 2, + "DependencyLength": 3 + } + }, + { + "Name": "FunctionControl", + "Type": "Bit", + "Values": + { + "Inline": 0, + "DontInline": 1, + "Pure": 2, + "Const": 3 + } + }, + { + "Name": "MemorySemantics", + "Type": "Bit", + "Values": + { + "Acquire": 1, + "Release": 2, + "AcquireRelease": 3, + "SequentiallyConsistent": 4, + "UniformMemory": 6, + "SubgroupMemory": 7, + "WorkgroupMemory": 8, + "CrossWorkgroupMemory": 9, + "AtomicCounterMemory": 10, + "ImageMemory": 11 + } + }, + { + "Name": "MemoryAccess", + "Type": "Bit", + "Values": + { + "Volatile": 0, + "Aligned": 1, + "Nontemporal": 2 + } + }, + { + "Name": "Scope", + "Type": "Value", + "Values": + { + "CrossDevice": 0, + "Device": 1, + "Workgroup": 2, + "Subgroup": 3, + "Invocation": 4 + } + }, + { + "Name": "GroupOperation", + "Type": "Value", + "Values": + { + "Reduce": 0, + "InclusiveScan": 1, + "ExclusiveScan": 2 + } + }, + { + "Name": "KernelEnqueueFlags", + "Type": "Value", + "Values": + { + "NoWait": 0, + "WaitKernel": 1, + "WaitWorkGroup": 2 + } + }, + { + "Name": "KernelProfilingInfo", + "Type": "Bit", + "Values": + { + "CmdExecTime": 0 + } + }, + { + "Name": "Capability", + "Type": "Value", + "Values": + { + "Matrix": 0, + "Shader": 1, + "Geometry": 2, + "Tessellation": 3, + "Addresses": 4, + "Linkage": 5, + "Kernel": 6, + "Vector16": 7, + "Float16Buffer": 8, + "Float16": 9, + "Float64": 10, + "Int64": 11, + "Int64Atomics": 12, + "ImageBasic": 13, + "ImageReadWrite": 14, + "ImageMipmap": 15, + "Pipes": 17, + "Groups": 18, + "DeviceEnqueue": 19, + "LiteralSampler": 20, + "AtomicStorage": 21, + "Int16": 22, + "TessellationPointSize": 23, + "GeometryPointSize": 24, + "ImageGatherExtended": 25, + "StorageImageMultisample": 27, + "UniformBufferArrayDynamicIndexing": 28, + "SampledImageArrayDynamicIndexing": 29, + "StorageBufferArrayDynamicIndexing": 30, + "StorageImageArrayDynamicIndexing": 31, + "ClipDistance": 32, + "CullDistance": 33, + "ImageCubeArray": 34, + "SampleRateShading": 35, + "ImageRect": 36, + "SampledRect": 37, + "GenericPointer": 38, + "Int8": 39, + "InputAttachment": 40, + "SparseResidency": 41, + "MinLod": 42, + "Sampled1D": 43, + "Image1D": 44, + "SampledCubeArray": 45, + "SampledBuffer": 46, + "ImageBuffer": 47, + "ImageMSArray": 48, + "StorageImageExtendedFormats": 49, + "ImageQuery": 50, + "DerivativeControl": 51, + "InterpolationFunction": 52, + "TransformFeedback": 53, + "GeometryStreams": 54, + "StorageImageReadWithoutFormat": 55, + "StorageImageWriteWithoutFormat": 56, + "MultiViewport": 57, + "SubgroupDispatch": 58, + "NamedBarrier": 59, + "PipeStorage": 60, + "SubgroupBallotKHR": 4423, + "DrawParameters": 4427, + "SubgroupVoteKHR": 4431, + "StorageBuffer16BitAccess": 4433, + "StorageUniformBufferBlock16": 4433, + "StorageUniform16": 4434, + "UniformAndStorageBuffer16BitAccess": 4434, + "StoragePushConstant16": 4435, + "StorageInputOutput16": 4436, + "DeviceGroup": 4437, + "MultiView": 4439, + "VariablePointersStorageBuffer": 4441, + "VariablePointers": 4442, + "AtomicStorageOps": 4445, + "SampleMaskPostDepthCoverage": 4447, + "ImageGatherBiasLodAMD": 5009, + "FragmentMaskAMD": 5010, + "StencilExportEXT": 5013, + "ImageReadWriteLodAMD": 5015, + "SampleMaskOverrideCoverageNV": 5249, + "GeometryShaderPassthroughNV": 5251, + "ShaderViewportIndexLayerEXT": 5254, + "ShaderViewportIndexLayerNV": 5254, + "ShaderViewportMaskNV": 5255, + "ShaderStereoViewNV": 5259, + "PerViewAttributesNV": 5260, + "SubgroupShuffleINTEL": 5568, + "SubgroupBufferBlockIOINTEL": 5569, + "SubgroupImageBlockIOINTEL": 5570 + } + }, + { + "Name": "Op", + "Type": "Value", + "Values": + { + "OpNop": 0, + "OpUndef": 1, + "OpSourceContinued": 2, + "OpSource": 3, + "OpSourceExtension": 4, + "OpName": 5, + "OpMemberName": 6, + "OpString": 7, + "OpLine": 8, + "OpExtension": 10, + "OpExtInstImport": 11, + "OpExtInst": 12, + "OpMemoryModel": 14, + "OpEntryPoint": 15, + "OpExecutionMode": 16, + "OpCapability": 17, + "OpTypeVoid": 19, + "OpTypeBool": 20, + "OpTypeInt": 21, + "OpTypeFloat": 22, + "OpTypeVector": 23, + "OpTypeMatrix": 24, + "OpTypeImage": 25, + "OpTypeSampler": 26, + "OpTypeSampledImage": 27, + "OpTypeArray": 28, + "OpTypeRuntimeArray": 29, + "OpTypeStruct": 30, + "OpTypeOpaque": 31, + "OpTypePointer": 32, + "OpTypeFunction": 33, + "OpTypeEvent": 34, + "OpTypeDeviceEvent": 35, + "OpTypeReserveId": 36, + "OpTypeQueue": 37, + "OpTypePipe": 38, + "OpTypeForwardPointer": 39, + "OpConstantTrue": 41, + "OpConstantFalse": 42, + "OpConstant": 43, + "OpConstantComposite": 44, + "OpConstantSampler": 45, + "OpConstantNull": 46, + "OpSpecConstantTrue": 48, + "OpSpecConstantFalse": 49, + "OpSpecConstant": 50, + "OpSpecConstantComposite": 51, + "OpSpecConstantOp": 52, + "OpFunction": 54, + "OpFunctionParameter": 55, + "OpFunctionEnd": 56, + "OpFunctionCall": 57, + "OpVariable": 59, + "OpImageTexelPointer": 60, + "OpLoad": 61, + "OpStore": 62, + "OpCopyMemory": 63, + "OpCopyMemorySized": 64, + "OpAccessChain": 65, + "OpInBoundsAccessChain": 66, + "OpPtrAccessChain": 67, + "OpArrayLength": 68, + "OpGenericPtrMemSemantics": 69, + "OpInBoundsPtrAccessChain": 70, + "OpDecorate": 71, + "OpMemberDecorate": 72, + "OpDecorationGroup": 73, + "OpGroupDecorate": 74, + "OpGroupMemberDecorate": 75, + "OpVectorExtractDynamic": 77, + "OpVectorInsertDynamic": 78, + "OpVectorShuffle": 79, + "OpCompositeConstruct": 80, + "OpCompositeExtract": 81, + "OpCompositeInsert": 82, + "OpCopyObject": 83, + "OpTranspose": 84, + "OpSampledImage": 86, + "OpImageSampleImplicitLod": 87, + "OpImageSampleExplicitLod": 88, + "OpImageSampleDrefImplicitLod": 89, + "OpImageSampleDrefExplicitLod": 90, + "OpImageSampleProjImplicitLod": 91, + "OpImageSampleProjExplicitLod": 92, + "OpImageSampleProjDrefImplicitLod": 93, + "OpImageSampleProjDrefExplicitLod": 94, + "OpImageFetch": 95, + "OpImageGather": 96, + "OpImageDrefGather": 97, + "OpImageRead": 98, + "OpImageWrite": 99, + "OpImage": 100, + "OpImageQueryFormat": 101, + "OpImageQueryOrder": 102, + "OpImageQuerySizeLod": 103, + "OpImageQuerySize": 104, + "OpImageQueryLod": 105, + "OpImageQueryLevels": 106, + "OpImageQuerySamples": 107, + "OpConvertFToU": 109, + "OpConvertFToS": 110, + "OpConvertSToF": 111, + "OpConvertUToF": 112, + "OpUConvert": 113, + "OpSConvert": 114, + "OpFConvert": 115, + "OpQuantizeToF16": 116, + "OpConvertPtrToU": 117, + "OpSatConvertSToU": 118, + "OpSatConvertUToS": 119, + "OpConvertUToPtr": 120, + "OpPtrCastToGeneric": 121, + "OpGenericCastToPtr": 122, + "OpGenericCastToPtrExplicit": 123, + "OpBitcast": 124, + "OpSNegate": 126, + "OpFNegate": 127, + "OpIAdd": 128, + "OpFAdd": 129, + "OpISub": 130, + "OpFSub": 131, + "OpIMul": 132, + "OpFMul": 133, + "OpUDiv": 134, + "OpSDiv": 135, + "OpFDiv": 136, + "OpUMod": 137, + "OpSRem": 138, + "OpSMod": 139, + "OpFRem": 140, + "OpFMod": 141, + "OpVectorTimesScalar": 142, + "OpMatrixTimesScalar": 143, + "OpVectorTimesMatrix": 144, + "OpMatrixTimesVector": 145, + "OpMatrixTimesMatrix": 146, + "OpOuterProduct": 147, + "OpDot": 148, + "OpIAddCarry": 149, + "OpISubBorrow": 150, + "OpUMulExtended": 151, + "OpSMulExtended": 152, + "OpAny": 154, + "OpAll": 155, + "OpIsNan": 156, + "OpIsInf": 157, + "OpIsFinite": 158, + "OpIsNormal": 159, + "OpSignBitSet": 160, + "OpLessOrGreater": 161, + "OpOrdered": 162, + "OpUnordered": 163, + "OpLogicalEqual": 164, + "OpLogicalNotEqual": 165, + "OpLogicalOr": 166, + "OpLogicalAnd": 167, + "OpLogicalNot": 168, + "OpSelect": 169, + "OpIEqual": 170, + "OpINotEqual": 171, + "OpUGreaterThan": 172, + "OpSGreaterThan": 173, + "OpUGreaterThanEqual": 174, + "OpSGreaterThanEqual": 175, + "OpULessThan": 176, + "OpSLessThan": 177, + "OpULessThanEqual": 178, + "OpSLessThanEqual": 179, + "OpFOrdEqual": 180, + "OpFUnordEqual": 181, + "OpFOrdNotEqual": 182, + "OpFUnordNotEqual": 183, + "OpFOrdLessThan": 184, + "OpFUnordLessThan": 185, + "OpFOrdGreaterThan": 186, + "OpFUnordGreaterThan": 187, + "OpFOrdLessThanEqual": 188, + "OpFUnordLessThanEqual": 189, + "OpFOrdGreaterThanEqual": 190, + "OpFUnordGreaterThanEqual": 191, + "OpShiftRightLogical": 194, + "OpShiftRightArithmetic": 195, + "OpShiftLeftLogical": 196, + "OpBitwiseOr": 197, + "OpBitwiseXor": 198, + "OpBitwiseAnd": 199, + "OpNot": 200, + "OpBitFieldInsert": 201, + "OpBitFieldSExtract": 202, + "OpBitFieldUExtract": 203, + "OpBitReverse": 204, + "OpBitCount": 205, + "OpDPdx": 207, + "OpDPdy": 208, + "OpFwidth": 209, + "OpDPdxFine": 210, + "OpDPdyFine": 211, + "OpFwidthFine": 212, + "OpDPdxCoarse": 213, + "OpDPdyCoarse": 214, + "OpFwidthCoarse": 215, + "OpEmitVertex": 218, + "OpEndPrimitive": 219, + "OpEmitStreamVertex": 220, + "OpEndStreamPrimitive": 221, + "OpControlBarrier": 224, + "OpMemoryBarrier": 225, + "OpAtomicLoad": 227, + "OpAtomicStore": 228, + "OpAtomicExchange": 229, + "OpAtomicCompareExchange": 230, + "OpAtomicCompareExchangeWeak": 231, + "OpAtomicIIncrement": 232, + "OpAtomicIDecrement": 233, + "OpAtomicIAdd": 234, + "OpAtomicISub": 235, + "OpAtomicSMin": 236, + "OpAtomicUMin": 237, + "OpAtomicSMax": 238, + "OpAtomicUMax": 239, + "OpAtomicAnd": 240, + "OpAtomicOr": 241, + "OpAtomicXor": 242, + "OpPhi": 245, + "OpLoopMerge": 246, + "OpSelectionMerge": 247, + "OpLabel": 248, + "OpBranch": 249, + "OpBranchConditional": 250, + "OpSwitch": 251, + "OpKill": 252, + "OpReturn": 253, + "OpReturnValue": 254, + "OpUnreachable": 255, + "OpLifetimeStart": 256, + "OpLifetimeStop": 257, + "OpGroupAsyncCopy": 259, + "OpGroupWaitEvents": 260, + "OpGroupAll": 261, + "OpGroupAny": 262, + "OpGroupBroadcast": 263, + "OpGroupIAdd": 264, + "OpGroupFAdd": 265, + "OpGroupFMin": 266, + "OpGroupUMin": 267, + "OpGroupSMin": 268, + "OpGroupFMax": 269, + "OpGroupUMax": 270, + "OpGroupSMax": 271, + "OpReadPipe": 274, + "OpWritePipe": 275, + "OpReservedReadPipe": 276, + "OpReservedWritePipe": 277, + "OpReserveReadPipePackets": 278, + "OpReserveWritePipePackets": 279, + "OpCommitReadPipe": 280, + "OpCommitWritePipe": 281, + "OpIsValidReserveId": 282, + "OpGetNumPipePackets": 283, + "OpGetMaxPipePackets": 284, + "OpGroupReserveReadPipePackets": 285, + "OpGroupReserveWritePipePackets": 286, + "OpGroupCommitReadPipe": 287, + "OpGroupCommitWritePipe": 288, + "OpEnqueueMarker": 291, + "OpEnqueueKernel": 292, + "OpGetKernelNDrangeSubGroupCount": 293, + "OpGetKernelNDrangeMaxSubGroupSize": 294, + "OpGetKernelWorkGroupSize": 295, + "OpGetKernelPreferredWorkGroupSizeMultiple": 296, + "OpRetainEvent": 297, + "OpReleaseEvent": 298, + "OpCreateUserEvent": 299, + "OpIsValidEvent": 300, + "OpSetUserEventStatus": 301, + "OpCaptureEventProfilingInfo": 302, + "OpGetDefaultQueue": 303, + "OpBuildNDRange": 304, + "OpImageSparseSampleImplicitLod": 305, + "OpImageSparseSampleExplicitLod": 306, + "OpImageSparseSampleDrefImplicitLod": 307, + "OpImageSparseSampleDrefExplicitLod": 308, + "OpImageSparseSampleProjImplicitLod": 309, + "OpImageSparseSampleProjExplicitLod": 310, + "OpImageSparseSampleProjDrefImplicitLod": 311, + "OpImageSparseSampleProjDrefExplicitLod": 312, + "OpImageSparseFetch": 313, + "OpImageSparseGather": 314, + "OpImageSparseDrefGather": 315, + "OpImageSparseTexelsResident": 316, + "OpNoLine": 317, + "OpAtomicFlagTestAndSet": 318, + "OpAtomicFlagClear": 319, + "OpImageSparseRead": 320, + "OpSizeOf": 321, + "OpTypePipeStorage": 322, + "OpConstantPipeStorage": 323, + "OpCreatePipeFromPipeStorage": 324, + "OpGetKernelLocalSizeForSubgroupCount": 325, + "OpGetKernelMaxNumSubgroups": 326, + "OpTypeNamedBarrier": 327, + "OpNamedBarrierInitialize": 328, + "OpMemoryNamedBarrier": 329, + "OpModuleProcessed": 330, + "OpSubgroupBallotKHR": 4421, + "OpSubgroupFirstInvocationKHR": 4422, + "OpSubgroupAllKHR": 4428, + "OpSubgroupAnyKHR": 4429, + "OpSubgroupAllEqualKHR": 4430, + "OpSubgroupReadInvocationKHR": 4432, + "OpGroupIAddNonUniformAMD": 5000, + "OpGroupFAddNonUniformAMD": 5001, + "OpGroupFMinNonUniformAMD": 5002, + "OpGroupUMinNonUniformAMD": 5003, + "OpGroupSMinNonUniformAMD": 5004, + "OpGroupFMaxNonUniformAMD": 5005, + "OpGroupUMaxNonUniformAMD": 5006, + "OpGroupSMaxNonUniformAMD": 5007, + "OpFragmentMaskFetchAMD": 5011, + "OpFragmentFetchAMD": 5012, + "OpSubgroupShuffleINTEL": 5571, + "OpSubgroupShuffleDownINTEL": 5572, + "OpSubgroupShuffleUpINTEL": 5573, + "OpSubgroupShuffleXorINTEL": 5574, + "OpSubgroupBlockReadINTEL": 5575, + "OpSubgroupBlockWriteINTEL": 5576, + "OpSubgroupImageBlockReadINTEL": 5577, + "OpSubgroupImageBlockWriteINTEL": 5578 + } + } + ] + } +} + diff --git a/ext/vulkan/spirv.lua b/ext/vulkan/spirv.lua index 421c1f45bb..44688596cd 100644 --- a/ext/vulkan/spirv.lua +++ b/ext/vulkan/spirv.lua @@ -1,921 +1,966 @@ --- Copyright (c) 2014-2017 The Khronos Group Inc. --- --- Permission is hereby granted, free of charge, to any person obtaining a copy --- of this software and/or associated documentation files (the "Materials"), --- to deal in the Materials without restriction, including without limitation --- the rights to use, copy, modify, merge, publish, distribute, sublicense, --- and/or sell copies of the Materials, and to permit persons to whom the --- Materials are furnished to do so, subject to the following conditions: --- --- The above copyright notice and this permission notice shall be included in --- all copies or substantial portions of the Materials. --- --- MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS --- STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND --- HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ --- --- THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS --- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL --- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING --- FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS --- IN THE MATERIALS. - --- This header is automatically generated by the same tool that creates --- the Binary Section of the SPIR-V specification. - --- Enumeration tokens for SPIR-V, in various styles: --- C, C++, C++11, JSON, Lua, Python --- --- - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL --- - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL --- - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL --- - Lua will use tables, e.g.: spv.SourceLanguage.GLSL --- - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] --- --- Some tokens act like mask values, which can be OR'd together, --- while others are mutually exclusive. The mask-like ones have --- "Mask" in their name, and a parallel enum that has the shift --- amount (1 << x) for each corresponding enumerant. - -spv = { - MagicNumber = 0x07230203, - Version = 0x00010100, - Revision = 6, - OpCodeMask = 0xffff, - WordCountShift = 16, - - SourceLanguage = { - Unknown = 0, - ESSL = 1, - GLSL = 2, - OpenCL_C = 3, - OpenCL_CPP = 4, - }, - - ExecutionModel = { - Vertex = 0, - TessellationControl = 1, - TessellationEvaluation = 2, - Geometry = 3, - Fragment = 4, - GLCompute = 5, - Kernel = 6, - }, - - AddressingModel = { - Logical = 0, - Physical32 = 1, - Physical64 = 2, - }, - - MemoryModel = { - Simple = 0, - GLSL450 = 1, - OpenCL = 2, - }, - - ExecutionMode = { - Invocations = 0, - SpacingEqual = 1, - SpacingFractionalEven = 2, - SpacingFractionalOdd = 3, - VertexOrderCw = 4, - VertexOrderCcw = 5, - PixelCenterInteger = 6, - OriginUpperLeft = 7, - OriginLowerLeft = 8, - EarlyFragmentTests = 9, - PointMode = 10, - Xfb = 11, - DepthReplacing = 12, - DepthGreater = 14, - DepthLess = 15, - DepthUnchanged = 16, - LocalSize = 17, - LocalSizeHint = 18, - InputPoints = 19, - InputLines = 20, - InputLinesAdjacency = 21, - Triangles = 22, - InputTrianglesAdjacency = 23, - Quads = 24, - Isolines = 25, - OutputVertices = 26, - OutputPoints = 27, - OutputLineStrip = 28, - OutputTriangleStrip = 29, - VecTypeHint = 30, - ContractionOff = 31, - Initializer = 33, - Finalizer = 34, - SubgroupSize = 35, - SubgroupsPerWorkgroup = 36, - }, - - StorageClass = { - UniformConstant = 0, - Input = 1, - Uniform = 2, - Output = 3, - Workgroup = 4, - CrossWorkgroup = 5, - Private = 6, - Function = 7, - Generic = 8, - PushConstant = 9, - AtomicCounter = 10, - Image = 11, - }, - - Dim = { - Dim1D = 0, - Dim2D = 1, - Dim3D = 2, - Cube = 3, - Rect = 4, - Buffer = 5, - SubpassData = 6, - }, - - SamplerAddressingMode = { - None = 0, - ClampToEdge = 1, - Clamp = 2, - Repeat = 3, - RepeatMirrored = 4, - }, - - SamplerFilterMode = { - Nearest = 0, - Linear = 1, - }, - - ImageFormat = { - Unknown = 0, - Rgba32f = 1, - Rgba16f = 2, - R32f = 3, - Rgba8 = 4, - Rgba8Snorm = 5, - Rg32f = 6, - Rg16f = 7, - R11fG11fB10f = 8, - R16f = 9, - Rgba16 = 10, - Rgb10A2 = 11, - Rg16 = 12, - Rg8 = 13, - R16 = 14, - R8 = 15, - Rgba16Snorm = 16, - Rg16Snorm = 17, - Rg8Snorm = 18, - R16Snorm = 19, - R8Snorm = 20, - Rgba32i = 21, - Rgba16i = 22, - Rgba8i = 23, - R32i = 24, - Rg32i = 25, - Rg16i = 26, - Rg8i = 27, - R16i = 28, - R8i = 29, - Rgba32ui = 30, - Rgba16ui = 31, - Rgba8ui = 32, - R32ui = 33, - Rgb10a2ui = 34, - Rg32ui = 35, - Rg16ui = 36, - Rg8ui = 37, - R16ui = 38, - R8ui = 39, - }, - - ImageChannelOrder = { - R = 0, - A = 1, - RG = 2, - RA = 3, - RGB = 4, - RGBA = 5, - BGRA = 6, - ARGB = 7, - Intensity = 8, - Luminance = 9, - Rx = 10, - RGx = 11, - RGBx = 12, - Depth = 13, - DepthStencil = 14, - sRGB = 15, - sRGBx = 16, - sRGBA = 17, - sBGRA = 18, - ABGR = 19, - }, - - ImageChannelDataType = { - SnormInt8 = 0, - SnormInt16 = 1, - UnormInt8 = 2, - UnormInt16 = 3, - UnormShort565 = 4, - UnormShort555 = 5, - UnormInt101010 = 6, - SignedInt8 = 7, - SignedInt16 = 8, - SignedInt32 = 9, - UnsignedInt8 = 10, - UnsignedInt16 = 11, - UnsignedInt32 = 12, - HalfFloat = 13, - Float = 14, - UnormInt24 = 15, - UnormInt101010_2 = 16, - }, - - ImageOperandsShift = { - Bias = 0, - Lod = 1, - Grad = 2, - ConstOffset = 3, - Offset = 4, - ConstOffsets = 5, - Sample = 6, - MinLod = 7, - }, - - ImageOperandsMask = { - MaskNone = 0, - Bias = 0x00000001, - Lod = 0x00000002, - Grad = 0x00000004, - ConstOffset = 0x00000008, - Offset = 0x00000010, - ConstOffsets = 0x00000020, - Sample = 0x00000040, - MinLod = 0x00000080, - }, - - FPFastMathModeShift = { - NotNaN = 0, - NotInf = 1, - NSZ = 2, - AllowRecip = 3, - Fast = 4, - }, - - FPFastMathModeMask = { - MaskNone = 0, - NotNaN = 0x00000001, - NotInf = 0x00000002, - NSZ = 0x00000004, - AllowRecip = 0x00000008, - Fast = 0x00000010, - }, - - FPRoundingMode = { - RTE = 0, - RTZ = 1, - RTP = 2, - RTN = 3, - }, - - LinkageType = { - Export = 0, - Import = 1, - }, - - AccessQualifier = { - ReadOnly = 0, - WriteOnly = 1, - ReadWrite = 2, - }, - - FunctionParameterAttribute = { - Zext = 0, - Sext = 1, - ByVal = 2, - Sret = 3, - NoAlias = 4, - NoCapture = 5, - NoWrite = 6, - NoReadWrite = 7, - }, - - Decoration = { - RelaxedPrecision = 0, - SpecId = 1, - Block = 2, - BufferBlock = 3, - RowMajor = 4, - ColMajor = 5, - ArrayStride = 6, - MatrixStride = 7, - GLSLShared = 8, - GLSLPacked = 9, - CPacked = 10, - BuiltIn = 11, - NoPerspective = 13, - Flat = 14, - Patch = 15, - Centroid = 16, - Sample = 17, - Invariant = 18, - Restrict = 19, - Aliased = 20, - Volatile = 21, - Constant = 22, - Coherent = 23, - NonWritable = 24, - NonReadable = 25, - Uniform = 26, - SaturatedConversion = 28, - Stream = 29, - Location = 30, - Component = 31, - Index = 32, - Binding = 33, - DescriptorSet = 34, - Offset = 35, - XfbBuffer = 36, - XfbStride = 37, - FuncParamAttr = 38, - FPRoundingMode = 39, - FPFastMathMode = 40, - LinkageAttributes = 41, - NoContraction = 42, - InputAttachmentIndex = 43, - Alignment = 44, - MaxByteOffset = 45, - OverrideCoverageNV = 5248, - PassthroughNV = 5250, - ViewportRelativeNV = 5252, - SecondaryViewportRelativeNV = 5256, - }, - - BuiltIn = { - Position = 0, - PointSize = 1, - ClipDistance = 3, - CullDistance = 4, - VertexId = 5, - InstanceId = 6, - PrimitiveId = 7, - InvocationId = 8, - Layer = 9, - ViewportIndex = 10, - TessLevelOuter = 11, - TessLevelInner = 12, - TessCoord = 13, - PatchVertices = 14, - FragCoord = 15, - PointCoord = 16, - FrontFacing = 17, - SampleId = 18, - SamplePosition = 19, - SampleMask = 20, - FragDepth = 22, - HelperInvocation = 23, - NumWorkgroups = 24, - WorkgroupSize = 25, - WorkgroupId = 26, - LocalInvocationId = 27, - GlobalInvocationId = 28, - LocalInvocationIndex = 29, - WorkDim = 30, - GlobalSize = 31, - EnqueuedWorkgroupSize = 32, - GlobalOffset = 33, - GlobalLinearId = 34, - SubgroupSize = 36, - SubgroupMaxSize = 37, - NumSubgroups = 38, - NumEnqueuedSubgroups = 39, - SubgroupId = 40, - SubgroupLocalInvocationId = 41, - VertexIndex = 42, - InstanceIndex = 43, - SubgroupEqMaskKHR = 4416, - SubgroupGeMaskKHR = 4417, - SubgroupGtMaskKHR = 4418, - SubgroupLeMaskKHR = 4419, - SubgroupLtMaskKHR = 4420, - BaseVertex = 4424, - BaseInstance = 4425, - DrawIndex = 4426, - DeviceIndex = 4438, - ViewIndex = 4440, - ViewportMaskNV = 5253, - SecondaryPositionNV = 5257, - SecondaryViewportMaskNV = 5258, - PositionPerViewNV = 5261, - ViewportMaskPerViewNV = 5262, - }, - - SelectionControlShift = { - Flatten = 0, - DontFlatten = 1, - }, - - SelectionControlMask = { - MaskNone = 0, - Flatten = 0x00000001, - DontFlatten = 0x00000002, - }, - - LoopControlShift = { - Unroll = 0, - DontUnroll = 1, - DependencyInfinite = 2, - DependencyLength = 3, - }, - - LoopControlMask = { - MaskNone = 0, - Unroll = 0x00000001, - DontUnroll = 0x00000002, - DependencyInfinite = 0x00000004, - DependencyLength = 0x00000008, - }, - - FunctionControlShift = { - Inline = 0, - DontInline = 1, - Pure = 2, - Const = 3, - }, - - FunctionControlMask = { - MaskNone = 0, - Inline = 0x00000001, - DontInline = 0x00000002, - Pure = 0x00000004, - Const = 0x00000008, - }, - - MemorySemanticsShift = { - Acquire = 1, - Release = 2, - AcquireRelease = 3, - SequentiallyConsistent = 4, - UniformMemory = 6, - SubgroupMemory = 7, - WorkgroupMemory = 8, - CrossWorkgroupMemory = 9, - AtomicCounterMemory = 10, - ImageMemory = 11, - }, - - MemorySemanticsMask = { - MaskNone = 0, - Acquire = 0x00000002, - Release = 0x00000004, - AcquireRelease = 0x00000008, - SequentiallyConsistent = 0x00000010, - UniformMemory = 0x00000040, - SubgroupMemory = 0x00000080, - WorkgroupMemory = 0x00000100, - CrossWorkgroupMemory = 0x00000200, - AtomicCounterMemory = 0x00000400, - ImageMemory = 0x00000800, - }, - - MemoryAccessShift = { - Volatile = 0, - Aligned = 1, - Nontemporal = 2, - }, - - MemoryAccessMask = { - MaskNone = 0, - Volatile = 0x00000001, - Aligned = 0x00000002, - Nontemporal = 0x00000004, - }, - - Scope = { - CrossDevice = 0, - Device = 1, - Workgroup = 2, - Subgroup = 3, - Invocation = 4, - }, - - GroupOperation = { - Reduce = 0, - InclusiveScan = 1, - ExclusiveScan = 2, - }, - - KernelEnqueueFlags = { - NoWait = 0, - WaitKernel = 1, - WaitWorkGroup = 2, - }, - - KernelProfilingInfoShift = { - CmdExecTime = 0, - }, - - KernelProfilingInfoMask = { - MaskNone = 0, - CmdExecTime = 0x00000001, - }, - - Capability = { - Matrix = 0, - Shader = 1, - Geometry = 2, - Tessellation = 3, - Addresses = 4, - Linkage = 5, - Kernel = 6, - Vector16 = 7, - Float16Buffer = 8, - Float16 = 9, - Float64 = 10, - Int64 = 11, - Int64Atomics = 12, - ImageBasic = 13, - ImageReadWrite = 14, - ImageMipmap = 15, - Pipes = 17, - Groups = 18, - DeviceEnqueue = 19, - LiteralSampler = 20, - AtomicStorage = 21, - Int16 = 22, - TessellationPointSize = 23, - GeometryPointSize = 24, - ImageGatherExtended = 25, - StorageImageMultisample = 27, - UniformBufferArrayDynamicIndexing = 28, - SampledImageArrayDynamicIndexing = 29, - StorageBufferArrayDynamicIndexing = 30, - StorageImageArrayDynamicIndexing = 31, - ClipDistance = 32, - CullDistance = 33, - ImageCubeArray = 34, - SampleRateShading = 35, - ImageRect = 36, - SampledRect = 37, - GenericPointer = 38, - Int8 = 39, - InputAttachment = 40, - SparseResidency = 41, - MinLod = 42, - Sampled1D = 43, - Image1D = 44, - SampledCubeArray = 45, - SampledBuffer = 46, - ImageBuffer = 47, - ImageMSArray = 48, - StorageImageExtendedFormats = 49, - ImageQuery = 50, - DerivativeControl = 51, - InterpolationFunction = 52, - TransformFeedback = 53, - GeometryStreams = 54, - StorageImageReadWithoutFormat = 55, - StorageImageWriteWithoutFormat = 56, - MultiViewport = 57, - SubgroupDispatch = 58, - NamedBarrier = 59, - PipeStorage = 60, - SubgroupBallotKHR = 4423, - DrawParameters = 4427, - SubgroupVoteKHR = 4431, - StorageUniformBufferBlock16 = 4433, - StorageUniform16 = 4434, - StoragePushConstant16 = 4435, - StorageInputOutput16 = 4436, - DeviceGroup = 4437, - MultiView = 4439, - SampleMaskOverrideCoverageNV = 5249, - GeometryShaderPassthroughNV = 5251, - ShaderViewportIndexLayerNV = 5254, - ShaderViewportMaskNV = 5255, - ShaderStereoViewNV = 5259, - PerViewAttributesNV = 5260, - }, - - Op = { - OpNop = 0, - OpUndef = 1, - OpSourceContinued = 2, - OpSource = 3, - OpSourceExtension = 4, - OpName = 5, - OpMemberName = 6, - OpString = 7, - OpLine = 8, - OpExtension = 10, - OpExtInstImport = 11, - OpExtInst = 12, - OpMemoryModel = 14, - OpEntryPoint = 15, - OpExecutionMode = 16, - OpCapability = 17, - OpTypeVoid = 19, - OpTypeBool = 20, - OpTypeInt = 21, - OpTypeFloat = 22, - OpTypeVector = 23, - OpTypeMatrix = 24, - OpTypeImage = 25, - OpTypeSampler = 26, - OpTypeSampledImage = 27, - OpTypeArray = 28, - OpTypeRuntimeArray = 29, - OpTypeStruct = 30, - OpTypeOpaque = 31, - OpTypePointer = 32, - OpTypeFunction = 33, - OpTypeEvent = 34, - OpTypeDeviceEvent = 35, - OpTypeReserveId = 36, - OpTypeQueue = 37, - OpTypePipe = 38, - OpTypeForwardPointer = 39, - OpConstantTrue = 41, - OpConstantFalse = 42, - OpConstant = 43, - OpConstantComposite = 44, - OpConstantSampler = 45, - OpConstantNull = 46, - OpSpecConstantTrue = 48, - OpSpecConstantFalse = 49, - OpSpecConstant = 50, - OpSpecConstantComposite = 51, - OpSpecConstantOp = 52, - OpFunction = 54, - OpFunctionParameter = 55, - OpFunctionEnd = 56, - OpFunctionCall = 57, - OpVariable = 59, - OpImageTexelPointer = 60, - OpLoad = 61, - OpStore = 62, - OpCopyMemory = 63, - OpCopyMemorySized = 64, - OpAccessChain = 65, - OpInBoundsAccessChain = 66, - OpPtrAccessChain = 67, - OpArrayLength = 68, - OpGenericPtrMemSemantics = 69, - OpInBoundsPtrAccessChain = 70, - OpDecorate = 71, - OpMemberDecorate = 72, - OpDecorationGroup = 73, - OpGroupDecorate = 74, - OpGroupMemberDecorate = 75, - OpVectorExtractDynamic = 77, - OpVectorInsertDynamic = 78, - OpVectorShuffle = 79, - OpCompositeConstruct = 80, - OpCompositeExtract = 81, - OpCompositeInsert = 82, - OpCopyObject = 83, - OpTranspose = 84, - OpSampledImage = 86, - OpImageSampleImplicitLod = 87, - OpImageSampleExplicitLod = 88, - OpImageSampleDrefImplicitLod = 89, - OpImageSampleDrefExplicitLod = 90, - OpImageSampleProjImplicitLod = 91, - OpImageSampleProjExplicitLod = 92, - OpImageSampleProjDrefImplicitLod = 93, - OpImageSampleProjDrefExplicitLod = 94, - OpImageFetch = 95, - OpImageGather = 96, - OpImageDrefGather = 97, - OpImageRead = 98, - OpImageWrite = 99, - OpImage = 100, - OpImageQueryFormat = 101, - OpImageQueryOrder = 102, - OpImageQuerySizeLod = 103, - OpImageQuerySize = 104, - OpImageQueryLod = 105, - OpImageQueryLevels = 106, - OpImageQuerySamples = 107, - OpConvertFToU = 109, - OpConvertFToS = 110, - OpConvertSToF = 111, - OpConvertUToF = 112, - OpUConvert = 113, - OpSConvert = 114, - OpFConvert = 115, - OpQuantizeToF16 = 116, - OpConvertPtrToU = 117, - OpSatConvertSToU = 118, - OpSatConvertUToS = 119, - OpConvertUToPtr = 120, - OpPtrCastToGeneric = 121, - OpGenericCastToPtr = 122, - OpGenericCastToPtrExplicit = 123, - OpBitcast = 124, - OpSNegate = 126, - OpFNegate = 127, - OpIAdd = 128, - OpFAdd = 129, - OpISub = 130, - OpFSub = 131, - OpIMul = 132, - OpFMul = 133, - OpUDiv = 134, - OpSDiv = 135, - OpFDiv = 136, - OpUMod = 137, - OpSRem = 138, - OpSMod = 139, - OpFRem = 140, - OpFMod = 141, - OpVectorTimesScalar = 142, - OpMatrixTimesScalar = 143, - OpVectorTimesMatrix = 144, - OpMatrixTimesVector = 145, - OpMatrixTimesMatrix = 146, - OpOuterProduct = 147, - OpDot = 148, - OpIAddCarry = 149, - OpISubBorrow = 150, - OpUMulExtended = 151, - OpSMulExtended = 152, - OpAny = 154, - OpAll = 155, - OpIsNan = 156, - OpIsInf = 157, - OpIsFinite = 158, - OpIsNormal = 159, - OpSignBitSet = 160, - OpLessOrGreater = 161, - OpOrdered = 162, - OpUnordered = 163, - OpLogicalEqual = 164, - OpLogicalNotEqual = 165, - OpLogicalOr = 166, - OpLogicalAnd = 167, - OpLogicalNot = 168, - OpSelect = 169, - OpIEqual = 170, - OpINotEqual = 171, - OpUGreaterThan = 172, - OpSGreaterThan = 173, - OpUGreaterThanEqual = 174, - OpSGreaterThanEqual = 175, - OpULessThan = 176, - OpSLessThan = 177, - OpULessThanEqual = 178, - OpSLessThanEqual = 179, - OpFOrdEqual = 180, - OpFUnordEqual = 181, - OpFOrdNotEqual = 182, - OpFUnordNotEqual = 183, - OpFOrdLessThan = 184, - OpFUnordLessThan = 185, - OpFOrdGreaterThan = 186, - OpFUnordGreaterThan = 187, - OpFOrdLessThanEqual = 188, - OpFUnordLessThanEqual = 189, - OpFOrdGreaterThanEqual = 190, - OpFUnordGreaterThanEqual = 191, - OpShiftRightLogical = 194, - OpShiftRightArithmetic = 195, - OpShiftLeftLogical = 196, - OpBitwiseOr = 197, - OpBitwiseXor = 198, - OpBitwiseAnd = 199, - OpNot = 200, - OpBitFieldInsert = 201, - OpBitFieldSExtract = 202, - OpBitFieldUExtract = 203, - OpBitReverse = 204, - OpBitCount = 205, - OpDPdx = 207, - OpDPdy = 208, - OpFwidth = 209, - OpDPdxFine = 210, - OpDPdyFine = 211, - OpFwidthFine = 212, - OpDPdxCoarse = 213, - OpDPdyCoarse = 214, - OpFwidthCoarse = 215, - OpEmitVertex = 218, - OpEndPrimitive = 219, - OpEmitStreamVertex = 220, - OpEndStreamPrimitive = 221, - OpControlBarrier = 224, - OpMemoryBarrier = 225, - OpAtomicLoad = 227, - OpAtomicStore = 228, - OpAtomicExchange = 229, - OpAtomicCompareExchange = 230, - OpAtomicCompareExchangeWeak = 231, - OpAtomicIIncrement = 232, - OpAtomicIDecrement = 233, - OpAtomicIAdd = 234, - OpAtomicISub = 235, - OpAtomicSMin = 236, - OpAtomicUMin = 237, - OpAtomicSMax = 238, - OpAtomicUMax = 239, - OpAtomicAnd = 240, - OpAtomicOr = 241, - OpAtomicXor = 242, - OpPhi = 245, - OpLoopMerge = 246, - OpSelectionMerge = 247, - OpLabel = 248, - OpBranch = 249, - OpBranchConditional = 250, - OpSwitch = 251, - OpKill = 252, - OpReturn = 253, - OpReturnValue = 254, - OpUnreachable = 255, - OpLifetimeStart = 256, - OpLifetimeStop = 257, - OpGroupAsyncCopy = 259, - OpGroupWaitEvents = 260, - OpGroupAll = 261, - OpGroupAny = 262, - OpGroupBroadcast = 263, - OpGroupIAdd = 264, - OpGroupFAdd = 265, - OpGroupFMin = 266, - OpGroupUMin = 267, - OpGroupSMin = 268, - OpGroupFMax = 269, - OpGroupUMax = 270, - OpGroupSMax = 271, - OpReadPipe = 274, - OpWritePipe = 275, - OpReservedReadPipe = 276, - OpReservedWritePipe = 277, - OpReserveReadPipePackets = 278, - OpReserveWritePipePackets = 279, - OpCommitReadPipe = 280, - OpCommitWritePipe = 281, - OpIsValidReserveId = 282, - OpGetNumPipePackets = 283, - OpGetMaxPipePackets = 284, - OpGroupReserveReadPipePackets = 285, - OpGroupReserveWritePipePackets = 286, - OpGroupCommitReadPipe = 287, - OpGroupCommitWritePipe = 288, - OpEnqueueMarker = 291, - OpEnqueueKernel = 292, - OpGetKernelNDrangeSubGroupCount = 293, - OpGetKernelNDrangeMaxSubGroupSize = 294, - OpGetKernelWorkGroupSize = 295, - OpGetKernelPreferredWorkGroupSizeMultiple = 296, - OpRetainEvent = 297, - OpReleaseEvent = 298, - OpCreateUserEvent = 299, - OpIsValidEvent = 300, - OpSetUserEventStatus = 301, - OpCaptureEventProfilingInfo = 302, - OpGetDefaultQueue = 303, - OpBuildNDRange = 304, - OpImageSparseSampleImplicitLod = 305, - OpImageSparseSampleExplicitLod = 306, - OpImageSparseSampleDrefImplicitLod = 307, - OpImageSparseSampleDrefExplicitLod = 308, - OpImageSparseSampleProjImplicitLod = 309, - OpImageSparseSampleProjExplicitLod = 310, - OpImageSparseSampleProjDrefImplicitLod = 311, - OpImageSparseSampleProjDrefExplicitLod = 312, - OpImageSparseFetch = 313, - OpImageSparseGather = 314, - OpImageSparseDrefGather = 315, - OpImageSparseTexelsResident = 316, - OpNoLine = 317, - OpAtomicFlagTestAndSet = 318, - OpAtomicFlagClear = 319, - OpImageSparseRead = 320, - OpSizeOf = 321, - OpTypePipeStorage = 322, - OpConstantPipeStorage = 323, - OpCreatePipeFromPipeStorage = 324, - OpGetKernelLocalSizeForSubgroupCount = 325, - OpGetKernelMaxNumSubgroups = 326, - OpTypeNamedBarrier = 327, - OpNamedBarrierInitialize = 328, - OpMemoryNamedBarrier = 329, - OpModuleProcessed = 330, - OpSubgroupBallotKHR = 4421, - OpSubgroupFirstInvocationKHR = 4422, - OpSubgroupAllKHR = 4428, - OpSubgroupAnyKHR = 4429, - OpSubgroupAllEqualKHR = 4430, - OpSubgroupReadInvocationKHR = 4432, - }, - -} - +-- Copyright (c) 2014-2017 The Khronos Group Inc. +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy +-- of this software and/or associated documentation files (the "Materials"), +-- to deal in the Materials without restriction, including without limitation +-- the rights to use, copy, modify, merge, publish, distribute, sublicense, +-- and/or sell copies of the Materials, and to permit persons to whom the +-- Materials are furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in +-- all copies or substantial portions of the Materials. +-- +-- MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +-- STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +-- HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +-- +-- THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +-- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +-- FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +-- IN THE MATERIALS. + +-- This header is automatically generated by the same tool that creates +-- the Binary Section of the SPIR-V specification. + +-- Enumeration tokens for SPIR-V, in various styles: +-- C, C++, C++11, JSON, Lua, Python +-- +-- - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +-- - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +-- - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +-- - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +-- - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +-- +-- Some tokens act like mask values, which can be OR'd together, +-- while others are mutually exclusive. The mask-like ones have +-- "Mask" in their name, and a parallel enum that has the shift +-- amount (1 << x) for each corresponding enumerant. + +spv = { + MagicNumber = 0x07230203, + Version = 0x00010100, + Revision = 8, + OpCodeMask = 0xffff, + WordCountShift = 16, + + SourceLanguage = { + Unknown = 0, + ESSL = 1, + GLSL = 2, + OpenCL_C = 3, + OpenCL_CPP = 4, + HLSL = 5, + }, + + ExecutionModel = { + Vertex = 0, + TessellationControl = 1, + TessellationEvaluation = 2, + Geometry = 3, + Fragment = 4, + GLCompute = 5, + Kernel = 6, + }, + + AddressingModel = { + Logical = 0, + Physical32 = 1, + Physical64 = 2, + }, + + MemoryModel = { + Simple = 0, + GLSL450 = 1, + OpenCL = 2, + }, + + ExecutionMode = { + Invocations = 0, + SpacingEqual = 1, + SpacingFractionalEven = 2, + SpacingFractionalOdd = 3, + VertexOrderCw = 4, + VertexOrderCcw = 5, + PixelCenterInteger = 6, + OriginUpperLeft = 7, + OriginLowerLeft = 8, + EarlyFragmentTests = 9, + PointMode = 10, + Xfb = 11, + DepthReplacing = 12, + DepthGreater = 14, + DepthLess = 15, + DepthUnchanged = 16, + LocalSize = 17, + LocalSizeHint = 18, + InputPoints = 19, + InputLines = 20, + InputLinesAdjacency = 21, + Triangles = 22, + InputTrianglesAdjacency = 23, + Quads = 24, + Isolines = 25, + OutputVertices = 26, + OutputPoints = 27, + OutputLineStrip = 28, + OutputTriangleStrip = 29, + VecTypeHint = 30, + ContractionOff = 31, + Initializer = 33, + Finalizer = 34, + SubgroupSize = 35, + SubgroupsPerWorkgroup = 36, + PostDepthCoverage = 4446, + StencilRefReplacingEXT = 5027, + }, + + StorageClass = { + UniformConstant = 0, + Input = 1, + Uniform = 2, + Output = 3, + Workgroup = 4, + CrossWorkgroup = 5, + Private = 6, + Function = 7, + Generic = 8, + PushConstant = 9, + AtomicCounter = 10, + Image = 11, + StorageBuffer = 12, + }, + + Dim = { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + Cube = 3, + Rect = 4, + Buffer = 5, + SubpassData = 6, + }, + + SamplerAddressingMode = { + None = 0, + ClampToEdge = 1, + Clamp = 2, + Repeat = 3, + RepeatMirrored = 4, + }, + + SamplerFilterMode = { + Nearest = 0, + Linear = 1, + }, + + ImageFormat = { + Unknown = 0, + Rgba32f = 1, + Rgba16f = 2, + R32f = 3, + Rgba8 = 4, + Rgba8Snorm = 5, + Rg32f = 6, + Rg16f = 7, + R11fG11fB10f = 8, + R16f = 9, + Rgba16 = 10, + Rgb10A2 = 11, + Rg16 = 12, + Rg8 = 13, + R16 = 14, + R8 = 15, + Rgba16Snorm = 16, + Rg16Snorm = 17, + Rg8Snorm = 18, + R16Snorm = 19, + R8Snorm = 20, + Rgba32i = 21, + Rgba16i = 22, + Rgba8i = 23, + R32i = 24, + Rg32i = 25, + Rg16i = 26, + Rg8i = 27, + R16i = 28, + R8i = 29, + Rgba32ui = 30, + Rgba16ui = 31, + Rgba8ui = 32, + R32ui = 33, + Rgb10a2ui = 34, + Rg32ui = 35, + Rg16ui = 36, + Rg8ui = 37, + R16ui = 38, + R8ui = 39, + }, + + ImageChannelOrder = { + R = 0, + A = 1, + RG = 2, + RA = 3, + RGB = 4, + RGBA = 5, + BGRA = 6, + ARGB = 7, + Intensity = 8, + Luminance = 9, + Rx = 10, + RGx = 11, + RGBx = 12, + Depth = 13, + DepthStencil = 14, + sRGB = 15, + sRGBx = 16, + sRGBA = 17, + sBGRA = 18, + ABGR = 19, + }, + + ImageChannelDataType = { + SnormInt8 = 0, + SnormInt16 = 1, + UnormInt8 = 2, + UnormInt16 = 3, + UnormShort565 = 4, + UnormShort555 = 5, + UnormInt101010 = 6, + SignedInt8 = 7, + SignedInt16 = 8, + SignedInt32 = 9, + UnsignedInt8 = 10, + UnsignedInt16 = 11, + UnsignedInt32 = 12, + HalfFloat = 13, + Float = 14, + UnormInt24 = 15, + UnormInt101010_2 = 16, + }, + + ImageOperandsShift = { + Bias = 0, + Lod = 1, + Grad = 2, + ConstOffset = 3, + Offset = 4, + ConstOffsets = 5, + Sample = 6, + MinLod = 7, + }, + + ImageOperandsMask = { + MaskNone = 0, + Bias = 0x00000001, + Lod = 0x00000002, + Grad = 0x00000004, + ConstOffset = 0x00000008, + Offset = 0x00000010, + ConstOffsets = 0x00000020, + Sample = 0x00000040, + MinLod = 0x00000080, + }, + + FPFastMathModeShift = { + NotNaN = 0, + NotInf = 1, + NSZ = 2, + AllowRecip = 3, + Fast = 4, + }, + + FPFastMathModeMask = { + MaskNone = 0, + NotNaN = 0x00000001, + NotInf = 0x00000002, + NSZ = 0x00000004, + AllowRecip = 0x00000008, + Fast = 0x00000010, + }, + + FPRoundingMode = { + RTE = 0, + RTZ = 1, + RTP = 2, + RTN = 3, + }, + + LinkageType = { + Export = 0, + Import = 1, + }, + + AccessQualifier = { + ReadOnly = 0, + WriteOnly = 1, + ReadWrite = 2, + }, + + FunctionParameterAttribute = { + Zext = 0, + Sext = 1, + ByVal = 2, + Sret = 3, + NoAlias = 4, + NoCapture = 5, + NoWrite = 6, + NoReadWrite = 7, + }, + + Decoration = { + RelaxedPrecision = 0, + SpecId = 1, + Block = 2, + BufferBlock = 3, + RowMajor = 4, + ColMajor = 5, + ArrayStride = 6, + MatrixStride = 7, + GLSLShared = 8, + GLSLPacked = 9, + CPacked = 10, + BuiltIn = 11, + NoPerspective = 13, + Flat = 14, + Patch = 15, + Centroid = 16, + Sample = 17, + Invariant = 18, + Restrict = 19, + Aliased = 20, + Volatile = 21, + Constant = 22, + Coherent = 23, + NonWritable = 24, + NonReadable = 25, + Uniform = 26, + SaturatedConversion = 28, + Stream = 29, + Location = 30, + Component = 31, + Index = 32, + Binding = 33, + DescriptorSet = 34, + Offset = 35, + XfbBuffer = 36, + XfbStride = 37, + FuncParamAttr = 38, + FPRoundingMode = 39, + FPFastMathMode = 40, + LinkageAttributes = 41, + NoContraction = 42, + InputAttachmentIndex = 43, + Alignment = 44, + MaxByteOffset = 45, + ExplicitInterpAMD = 4999, + OverrideCoverageNV = 5248, + PassthroughNV = 5250, + ViewportRelativeNV = 5252, + SecondaryViewportRelativeNV = 5256, + }, + + BuiltIn = { + Position = 0, + PointSize = 1, + ClipDistance = 3, + CullDistance = 4, + VertexId = 5, + InstanceId = 6, + PrimitiveId = 7, + InvocationId = 8, + Layer = 9, + ViewportIndex = 10, + TessLevelOuter = 11, + TessLevelInner = 12, + TessCoord = 13, + PatchVertices = 14, + FragCoord = 15, + PointCoord = 16, + FrontFacing = 17, + SampleId = 18, + SamplePosition = 19, + SampleMask = 20, + FragDepth = 22, + HelperInvocation = 23, + NumWorkgroups = 24, + WorkgroupSize = 25, + WorkgroupId = 26, + LocalInvocationId = 27, + GlobalInvocationId = 28, + LocalInvocationIndex = 29, + WorkDim = 30, + GlobalSize = 31, + EnqueuedWorkgroupSize = 32, + GlobalOffset = 33, + GlobalLinearId = 34, + SubgroupSize = 36, + SubgroupMaxSize = 37, + NumSubgroups = 38, + NumEnqueuedSubgroups = 39, + SubgroupId = 40, + SubgroupLocalInvocationId = 41, + VertexIndex = 42, + InstanceIndex = 43, + SubgroupEqMaskKHR = 4416, + SubgroupGeMaskKHR = 4417, + SubgroupGtMaskKHR = 4418, + SubgroupLeMaskKHR = 4419, + SubgroupLtMaskKHR = 4420, + BaseVertex = 4424, + BaseInstance = 4425, + DrawIndex = 4426, + DeviceIndex = 4438, + ViewIndex = 4440, + BaryCoordNoPerspAMD = 4992, + BaryCoordNoPerspCentroidAMD = 4993, + BaryCoordNoPerspSampleAMD = 4994, + BaryCoordSmoothAMD = 4995, + BaryCoordSmoothCentroidAMD = 4996, + BaryCoordSmoothSampleAMD = 4997, + BaryCoordPullModelAMD = 4998, + FragStencilRefEXT = 5014, + ViewportMaskNV = 5253, + SecondaryPositionNV = 5257, + SecondaryViewportMaskNV = 5258, + PositionPerViewNV = 5261, + ViewportMaskPerViewNV = 5262, + }, + + SelectionControlShift = { + Flatten = 0, + DontFlatten = 1, + }, + + SelectionControlMask = { + MaskNone = 0, + Flatten = 0x00000001, + DontFlatten = 0x00000002, + }, + + LoopControlShift = { + Unroll = 0, + DontUnroll = 1, + DependencyInfinite = 2, + DependencyLength = 3, + }, + + LoopControlMask = { + MaskNone = 0, + Unroll = 0x00000001, + DontUnroll = 0x00000002, + DependencyInfinite = 0x00000004, + DependencyLength = 0x00000008, + }, + + FunctionControlShift = { + Inline = 0, + DontInline = 1, + Pure = 2, + Const = 3, + }, + + FunctionControlMask = { + MaskNone = 0, + Inline = 0x00000001, + DontInline = 0x00000002, + Pure = 0x00000004, + Const = 0x00000008, + }, + + MemorySemanticsShift = { + Acquire = 1, + Release = 2, + AcquireRelease = 3, + SequentiallyConsistent = 4, + UniformMemory = 6, + SubgroupMemory = 7, + WorkgroupMemory = 8, + CrossWorkgroupMemory = 9, + AtomicCounterMemory = 10, + ImageMemory = 11, + }, + + MemorySemanticsMask = { + MaskNone = 0, + Acquire = 0x00000002, + Release = 0x00000004, + AcquireRelease = 0x00000008, + SequentiallyConsistent = 0x00000010, + UniformMemory = 0x00000040, + SubgroupMemory = 0x00000080, + WorkgroupMemory = 0x00000100, + CrossWorkgroupMemory = 0x00000200, + AtomicCounterMemory = 0x00000400, + ImageMemory = 0x00000800, + }, + + MemoryAccessShift = { + Volatile = 0, + Aligned = 1, + Nontemporal = 2, + }, + + MemoryAccessMask = { + MaskNone = 0, + Volatile = 0x00000001, + Aligned = 0x00000002, + Nontemporal = 0x00000004, + }, + + Scope = { + CrossDevice = 0, + Device = 1, + Workgroup = 2, + Subgroup = 3, + Invocation = 4, + }, + + GroupOperation = { + Reduce = 0, + InclusiveScan = 1, + ExclusiveScan = 2, + }, + + KernelEnqueueFlags = { + NoWait = 0, + WaitKernel = 1, + WaitWorkGroup = 2, + }, + + KernelProfilingInfoShift = { + CmdExecTime = 0, + }, + + KernelProfilingInfoMask = { + MaskNone = 0, + CmdExecTime = 0x00000001, + }, + + Capability = { + Matrix = 0, + Shader = 1, + Geometry = 2, + Tessellation = 3, + Addresses = 4, + Linkage = 5, + Kernel = 6, + Vector16 = 7, + Float16Buffer = 8, + Float16 = 9, + Float64 = 10, + Int64 = 11, + Int64Atomics = 12, + ImageBasic = 13, + ImageReadWrite = 14, + ImageMipmap = 15, + Pipes = 17, + Groups = 18, + DeviceEnqueue = 19, + LiteralSampler = 20, + AtomicStorage = 21, + Int16 = 22, + TessellationPointSize = 23, + GeometryPointSize = 24, + ImageGatherExtended = 25, + StorageImageMultisample = 27, + UniformBufferArrayDynamicIndexing = 28, + SampledImageArrayDynamicIndexing = 29, + StorageBufferArrayDynamicIndexing = 30, + StorageImageArrayDynamicIndexing = 31, + ClipDistance = 32, + CullDistance = 33, + ImageCubeArray = 34, + SampleRateShading = 35, + ImageRect = 36, + SampledRect = 37, + GenericPointer = 38, + Int8 = 39, + InputAttachment = 40, + SparseResidency = 41, + MinLod = 42, + Sampled1D = 43, + Image1D = 44, + SampledCubeArray = 45, + SampledBuffer = 46, + ImageBuffer = 47, + ImageMSArray = 48, + StorageImageExtendedFormats = 49, + ImageQuery = 50, + DerivativeControl = 51, + InterpolationFunction = 52, + TransformFeedback = 53, + GeometryStreams = 54, + StorageImageReadWithoutFormat = 55, + StorageImageWriteWithoutFormat = 56, + MultiViewport = 57, + SubgroupDispatch = 58, + NamedBarrier = 59, + PipeStorage = 60, + SubgroupBallotKHR = 4423, + DrawParameters = 4427, + SubgroupVoteKHR = 4431, + StorageBuffer16BitAccess = 4433, + StorageUniformBufferBlock16 = 4433, + StorageUniform16 = 4434, + UniformAndStorageBuffer16BitAccess = 4434, + StoragePushConstant16 = 4435, + StorageInputOutput16 = 4436, + DeviceGroup = 4437, + MultiView = 4439, + VariablePointersStorageBuffer = 4441, + VariablePointers = 4442, + AtomicStorageOps = 4445, + SampleMaskPostDepthCoverage = 4447, + ImageGatherBiasLodAMD = 5009, + FragmentMaskAMD = 5010, + StencilExportEXT = 5013, + ImageReadWriteLodAMD = 5015, + SampleMaskOverrideCoverageNV = 5249, + GeometryShaderPassthroughNV = 5251, + ShaderViewportIndexLayerEXT = 5254, + ShaderViewportIndexLayerNV = 5254, + ShaderViewportMaskNV = 5255, + ShaderStereoViewNV = 5259, + PerViewAttributesNV = 5260, + SubgroupShuffleINTEL = 5568, + SubgroupBufferBlockIOINTEL = 5569, + SubgroupImageBlockIOINTEL = 5570, + }, + + Op = { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + }, + +} + diff --git a/ext/vulkan/spirv.py b/ext/vulkan/spirv.py index d0bce4d169..d7d900cb1d 100644 --- a/ext/vulkan/spirv.py +++ b/ext/vulkan/spirv.py @@ -1,921 +1,966 @@ -# Copyright (c) 2014-2017 The Khronos Group Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and/or associated documentation files (the "Materials"), -# to deal in the Materials without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Materials, and to permit persons to whom the -# Materials are furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Materials. -# -# MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -# STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -# HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -# -# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -# IN THE MATERIALS. - -# This header is automatically generated by the same tool that creates -# the Binary Section of the SPIR-V specification. - -# Enumeration tokens for SPIR-V, in various styles: -# C, C++, C++11, JSON, Lua, Python -# -# - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL -# - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL -# - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL -# - Lua will use tables, e.g.: spv.SourceLanguage.GLSL -# - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] -# -# Some tokens act like mask values, which can be OR'd together, -# while others are mutually exclusive. The mask-like ones have -# "Mask" in their name, and a parallel enum that has the shift -# amount (1 << x) for each corresponding enumerant. - -spv = { - 'MagicNumber' : 0x07230203, - 'Version' : 0x00010100, - 'Revision' : 6, - 'OpCodeMask' : 0xffff, - 'WordCountShift' : 16, - - 'SourceLanguage' : { - 'Unknown' : 0, - 'ESSL' : 1, - 'GLSL' : 2, - 'OpenCL_C' : 3, - 'OpenCL_CPP' : 4, - }, - - 'ExecutionModel' : { - 'Vertex' : 0, - 'TessellationControl' : 1, - 'TessellationEvaluation' : 2, - 'Geometry' : 3, - 'Fragment' : 4, - 'GLCompute' : 5, - 'Kernel' : 6, - }, - - 'AddressingModel' : { - 'Logical' : 0, - 'Physical32' : 1, - 'Physical64' : 2, - }, - - 'MemoryModel' : { - 'Simple' : 0, - 'GLSL450' : 1, - 'OpenCL' : 2, - }, - - 'ExecutionMode' : { - 'Invocations' : 0, - 'SpacingEqual' : 1, - 'SpacingFractionalEven' : 2, - 'SpacingFractionalOdd' : 3, - 'VertexOrderCw' : 4, - 'VertexOrderCcw' : 5, - 'PixelCenterInteger' : 6, - 'OriginUpperLeft' : 7, - 'OriginLowerLeft' : 8, - 'EarlyFragmentTests' : 9, - 'PointMode' : 10, - 'Xfb' : 11, - 'DepthReplacing' : 12, - 'DepthGreater' : 14, - 'DepthLess' : 15, - 'DepthUnchanged' : 16, - 'LocalSize' : 17, - 'LocalSizeHint' : 18, - 'InputPoints' : 19, - 'InputLines' : 20, - 'InputLinesAdjacency' : 21, - 'Triangles' : 22, - 'InputTrianglesAdjacency' : 23, - 'Quads' : 24, - 'Isolines' : 25, - 'OutputVertices' : 26, - 'OutputPoints' : 27, - 'OutputLineStrip' : 28, - 'OutputTriangleStrip' : 29, - 'VecTypeHint' : 30, - 'ContractionOff' : 31, - 'Initializer' : 33, - 'Finalizer' : 34, - 'SubgroupSize' : 35, - 'SubgroupsPerWorkgroup' : 36, - }, - - 'StorageClass' : { - 'UniformConstant' : 0, - 'Input' : 1, - 'Uniform' : 2, - 'Output' : 3, - 'Workgroup' : 4, - 'CrossWorkgroup' : 5, - 'Private' : 6, - 'Function' : 7, - 'Generic' : 8, - 'PushConstant' : 9, - 'AtomicCounter' : 10, - 'Image' : 11, - }, - - 'Dim' : { - 'Dim1D' : 0, - 'Dim2D' : 1, - 'Dim3D' : 2, - 'Cube' : 3, - 'Rect' : 4, - 'Buffer' : 5, - 'SubpassData' : 6, - }, - - 'SamplerAddressingMode' : { - 'None' : 0, - 'ClampToEdge' : 1, - 'Clamp' : 2, - 'Repeat' : 3, - 'RepeatMirrored' : 4, - }, - - 'SamplerFilterMode' : { - 'Nearest' : 0, - 'Linear' : 1, - }, - - 'ImageFormat' : { - 'Unknown' : 0, - 'Rgba32f' : 1, - 'Rgba16f' : 2, - 'R32f' : 3, - 'Rgba8' : 4, - 'Rgba8Snorm' : 5, - 'Rg32f' : 6, - 'Rg16f' : 7, - 'R11fG11fB10f' : 8, - 'R16f' : 9, - 'Rgba16' : 10, - 'Rgb10A2' : 11, - 'Rg16' : 12, - 'Rg8' : 13, - 'R16' : 14, - 'R8' : 15, - 'Rgba16Snorm' : 16, - 'Rg16Snorm' : 17, - 'Rg8Snorm' : 18, - 'R16Snorm' : 19, - 'R8Snorm' : 20, - 'Rgba32i' : 21, - 'Rgba16i' : 22, - 'Rgba8i' : 23, - 'R32i' : 24, - 'Rg32i' : 25, - 'Rg16i' : 26, - 'Rg8i' : 27, - 'R16i' : 28, - 'R8i' : 29, - 'Rgba32ui' : 30, - 'Rgba16ui' : 31, - 'Rgba8ui' : 32, - 'R32ui' : 33, - 'Rgb10a2ui' : 34, - 'Rg32ui' : 35, - 'Rg16ui' : 36, - 'Rg8ui' : 37, - 'R16ui' : 38, - 'R8ui' : 39, - }, - - 'ImageChannelOrder' : { - 'R' : 0, - 'A' : 1, - 'RG' : 2, - 'RA' : 3, - 'RGB' : 4, - 'RGBA' : 5, - 'BGRA' : 6, - 'ARGB' : 7, - 'Intensity' : 8, - 'Luminance' : 9, - 'Rx' : 10, - 'RGx' : 11, - 'RGBx' : 12, - 'Depth' : 13, - 'DepthStencil' : 14, - 'sRGB' : 15, - 'sRGBx' : 16, - 'sRGBA' : 17, - 'sBGRA' : 18, - 'ABGR' : 19, - }, - - 'ImageChannelDataType' : { - 'SnormInt8' : 0, - 'SnormInt16' : 1, - 'UnormInt8' : 2, - 'UnormInt16' : 3, - 'UnormShort565' : 4, - 'UnormShort555' : 5, - 'UnormInt101010' : 6, - 'SignedInt8' : 7, - 'SignedInt16' : 8, - 'SignedInt32' : 9, - 'UnsignedInt8' : 10, - 'UnsignedInt16' : 11, - 'UnsignedInt32' : 12, - 'HalfFloat' : 13, - 'Float' : 14, - 'UnormInt24' : 15, - 'UnormInt101010_2' : 16, - }, - - 'ImageOperandsShift' : { - 'Bias' : 0, - 'Lod' : 1, - 'Grad' : 2, - 'ConstOffset' : 3, - 'Offset' : 4, - 'ConstOffsets' : 5, - 'Sample' : 6, - 'MinLod' : 7, - }, - - 'ImageOperandsMask' : { - 'MaskNone' : 0, - 'Bias' : 0x00000001, - 'Lod' : 0x00000002, - 'Grad' : 0x00000004, - 'ConstOffset' : 0x00000008, - 'Offset' : 0x00000010, - 'ConstOffsets' : 0x00000020, - 'Sample' : 0x00000040, - 'MinLod' : 0x00000080, - }, - - 'FPFastMathModeShift' : { - 'NotNaN' : 0, - 'NotInf' : 1, - 'NSZ' : 2, - 'AllowRecip' : 3, - 'Fast' : 4, - }, - - 'FPFastMathModeMask' : { - 'MaskNone' : 0, - 'NotNaN' : 0x00000001, - 'NotInf' : 0x00000002, - 'NSZ' : 0x00000004, - 'AllowRecip' : 0x00000008, - 'Fast' : 0x00000010, - }, - - 'FPRoundingMode' : { - 'RTE' : 0, - 'RTZ' : 1, - 'RTP' : 2, - 'RTN' : 3, - }, - - 'LinkageType' : { - 'Export' : 0, - 'Import' : 1, - }, - - 'AccessQualifier' : { - 'ReadOnly' : 0, - 'WriteOnly' : 1, - 'ReadWrite' : 2, - }, - - 'FunctionParameterAttribute' : { - 'Zext' : 0, - 'Sext' : 1, - 'ByVal' : 2, - 'Sret' : 3, - 'NoAlias' : 4, - 'NoCapture' : 5, - 'NoWrite' : 6, - 'NoReadWrite' : 7, - }, - - 'Decoration' : { - 'RelaxedPrecision' : 0, - 'SpecId' : 1, - 'Block' : 2, - 'BufferBlock' : 3, - 'RowMajor' : 4, - 'ColMajor' : 5, - 'ArrayStride' : 6, - 'MatrixStride' : 7, - 'GLSLShared' : 8, - 'GLSLPacked' : 9, - 'CPacked' : 10, - 'BuiltIn' : 11, - 'NoPerspective' : 13, - 'Flat' : 14, - 'Patch' : 15, - 'Centroid' : 16, - 'Sample' : 17, - 'Invariant' : 18, - 'Restrict' : 19, - 'Aliased' : 20, - 'Volatile' : 21, - 'Constant' : 22, - 'Coherent' : 23, - 'NonWritable' : 24, - 'NonReadable' : 25, - 'Uniform' : 26, - 'SaturatedConversion' : 28, - 'Stream' : 29, - 'Location' : 30, - 'Component' : 31, - 'Index' : 32, - 'Binding' : 33, - 'DescriptorSet' : 34, - 'Offset' : 35, - 'XfbBuffer' : 36, - 'XfbStride' : 37, - 'FuncParamAttr' : 38, - 'FPRoundingMode' : 39, - 'FPFastMathMode' : 40, - 'LinkageAttributes' : 41, - 'NoContraction' : 42, - 'InputAttachmentIndex' : 43, - 'Alignment' : 44, - 'MaxByteOffset' : 45, - 'OverrideCoverageNV' : 5248, - 'PassthroughNV' : 5250, - 'ViewportRelativeNV' : 5252, - 'SecondaryViewportRelativeNV' : 5256, - }, - - 'BuiltIn' : { - 'Position' : 0, - 'PointSize' : 1, - 'ClipDistance' : 3, - 'CullDistance' : 4, - 'VertexId' : 5, - 'InstanceId' : 6, - 'PrimitiveId' : 7, - 'InvocationId' : 8, - 'Layer' : 9, - 'ViewportIndex' : 10, - 'TessLevelOuter' : 11, - 'TessLevelInner' : 12, - 'TessCoord' : 13, - 'PatchVertices' : 14, - 'FragCoord' : 15, - 'PointCoord' : 16, - 'FrontFacing' : 17, - 'SampleId' : 18, - 'SamplePosition' : 19, - 'SampleMask' : 20, - 'FragDepth' : 22, - 'HelperInvocation' : 23, - 'NumWorkgroups' : 24, - 'WorkgroupSize' : 25, - 'WorkgroupId' : 26, - 'LocalInvocationId' : 27, - 'GlobalInvocationId' : 28, - 'LocalInvocationIndex' : 29, - 'WorkDim' : 30, - 'GlobalSize' : 31, - 'EnqueuedWorkgroupSize' : 32, - 'GlobalOffset' : 33, - 'GlobalLinearId' : 34, - 'SubgroupSize' : 36, - 'SubgroupMaxSize' : 37, - 'NumSubgroups' : 38, - 'NumEnqueuedSubgroups' : 39, - 'SubgroupId' : 40, - 'SubgroupLocalInvocationId' : 41, - 'VertexIndex' : 42, - 'InstanceIndex' : 43, - 'SubgroupEqMaskKHR' : 4416, - 'SubgroupGeMaskKHR' : 4417, - 'SubgroupGtMaskKHR' : 4418, - 'SubgroupLeMaskKHR' : 4419, - 'SubgroupLtMaskKHR' : 4420, - 'BaseVertex' : 4424, - 'BaseInstance' : 4425, - 'DrawIndex' : 4426, - 'DeviceIndex' : 4438, - 'ViewIndex' : 4440, - 'ViewportMaskNV' : 5253, - 'SecondaryPositionNV' : 5257, - 'SecondaryViewportMaskNV' : 5258, - 'PositionPerViewNV' : 5261, - 'ViewportMaskPerViewNV' : 5262, - }, - - 'SelectionControlShift' : { - 'Flatten' : 0, - 'DontFlatten' : 1, - }, - - 'SelectionControlMask' : { - 'MaskNone' : 0, - 'Flatten' : 0x00000001, - 'DontFlatten' : 0x00000002, - }, - - 'LoopControlShift' : { - 'Unroll' : 0, - 'DontUnroll' : 1, - 'DependencyInfinite' : 2, - 'DependencyLength' : 3, - }, - - 'LoopControlMask' : { - 'MaskNone' : 0, - 'Unroll' : 0x00000001, - 'DontUnroll' : 0x00000002, - 'DependencyInfinite' : 0x00000004, - 'DependencyLength' : 0x00000008, - }, - - 'FunctionControlShift' : { - 'Inline' : 0, - 'DontInline' : 1, - 'Pure' : 2, - 'Const' : 3, - }, - - 'FunctionControlMask' : { - 'MaskNone' : 0, - 'Inline' : 0x00000001, - 'DontInline' : 0x00000002, - 'Pure' : 0x00000004, - 'Const' : 0x00000008, - }, - - 'MemorySemanticsShift' : { - 'Acquire' : 1, - 'Release' : 2, - 'AcquireRelease' : 3, - 'SequentiallyConsistent' : 4, - 'UniformMemory' : 6, - 'SubgroupMemory' : 7, - 'WorkgroupMemory' : 8, - 'CrossWorkgroupMemory' : 9, - 'AtomicCounterMemory' : 10, - 'ImageMemory' : 11, - }, - - 'MemorySemanticsMask' : { - 'MaskNone' : 0, - 'Acquire' : 0x00000002, - 'Release' : 0x00000004, - 'AcquireRelease' : 0x00000008, - 'SequentiallyConsistent' : 0x00000010, - 'UniformMemory' : 0x00000040, - 'SubgroupMemory' : 0x00000080, - 'WorkgroupMemory' : 0x00000100, - 'CrossWorkgroupMemory' : 0x00000200, - 'AtomicCounterMemory' : 0x00000400, - 'ImageMemory' : 0x00000800, - }, - - 'MemoryAccessShift' : { - 'Volatile' : 0, - 'Aligned' : 1, - 'Nontemporal' : 2, - }, - - 'MemoryAccessMask' : { - 'MaskNone' : 0, - 'Volatile' : 0x00000001, - 'Aligned' : 0x00000002, - 'Nontemporal' : 0x00000004, - }, - - 'Scope' : { - 'CrossDevice' : 0, - 'Device' : 1, - 'Workgroup' : 2, - 'Subgroup' : 3, - 'Invocation' : 4, - }, - - 'GroupOperation' : { - 'Reduce' : 0, - 'InclusiveScan' : 1, - 'ExclusiveScan' : 2, - }, - - 'KernelEnqueueFlags' : { - 'NoWait' : 0, - 'WaitKernel' : 1, - 'WaitWorkGroup' : 2, - }, - - 'KernelProfilingInfoShift' : { - 'CmdExecTime' : 0, - }, - - 'KernelProfilingInfoMask' : { - 'MaskNone' : 0, - 'CmdExecTime' : 0x00000001, - }, - - 'Capability' : { - 'Matrix' : 0, - 'Shader' : 1, - 'Geometry' : 2, - 'Tessellation' : 3, - 'Addresses' : 4, - 'Linkage' : 5, - 'Kernel' : 6, - 'Vector16' : 7, - 'Float16Buffer' : 8, - 'Float16' : 9, - 'Float64' : 10, - 'Int64' : 11, - 'Int64Atomics' : 12, - 'ImageBasic' : 13, - 'ImageReadWrite' : 14, - 'ImageMipmap' : 15, - 'Pipes' : 17, - 'Groups' : 18, - 'DeviceEnqueue' : 19, - 'LiteralSampler' : 20, - 'AtomicStorage' : 21, - 'Int16' : 22, - 'TessellationPointSize' : 23, - 'GeometryPointSize' : 24, - 'ImageGatherExtended' : 25, - 'StorageImageMultisample' : 27, - 'UniformBufferArrayDynamicIndexing' : 28, - 'SampledImageArrayDynamicIndexing' : 29, - 'StorageBufferArrayDynamicIndexing' : 30, - 'StorageImageArrayDynamicIndexing' : 31, - 'ClipDistance' : 32, - 'CullDistance' : 33, - 'ImageCubeArray' : 34, - 'SampleRateShading' : 35, - 'ImageRect' : 36, - 'SampledRect' : 37, - 'GenericPointer' : 38, - 'Int8' : 39, - 'InputAttachment' : 40, - 'SparseResidency' : 41, - 'MinLod' : 42, - 'Sampled1D' : 43, - 'Image1D' : 44, - 'SampledCubeArray' : 45, - 'SampledBuffer' : 46, - 'ImageBuffer' : 47, - 'ImageMSArray' : 48, - 'StorageImageExtendedFormats' : 49, - 'ImageQuery' : 50, - 'DerivativeControl' : 51, - 'InterpolationFunction' : 52, - 'TransformFeedback' : 53, - 'GeometryStreams' : 54, - 'StorageImageReadWithoutFormat' : 55, - 'StorageImageWriteWithoutFormat' : 56, - 'MultiViewport' : 57, - 'SubgroupDispatch' : 58, - 'NamedBarrier' : 59, - 'PipeStorage' : 60, - 'SubgroupBallotKHR' : 4423, - 'DrawParameters' : 4427, - 'SubgroupVoteKHR' : 4431, - 'StorageUniformBufferBlock16' : 4433, - 'StorageUniform16' : 4434, - 'StoragePushConstant16' : 4435, - 'StorageInputOutput16' : 4436, - 'DeviceGroup' : 4437, - 'MultiView' : 4439, - 'SampleMaskOverrideCoverageNV' : 5249, - 'GeometryShaderPassthroughNV' : 5251, - 'ShaderViewportIndexLayerNV' : 5254, - 'ShaderViewportMaskNV' : 5255, - 'ShaderStereoViewNV' : 5259, - 'PerViewAttributesNV' : 5260, - }, - - 'Op' : { - 'OpNop' : 0, - 'OpUndef' : 1, - 'OpSourceContinued' : 2, - 'OpSource' : 3, - 'OpSourceExtension' : 4, - 'OpName' : 5, - 'OpMemberName' : 6, - 'OpString' : 7, - 'OpLine' : 8, - 'OpExtension' : 10, - 'OpExtInstImport' : 11, - 'OpExtInst' : 12, - 'OpMemoryModel' : 14, - 'OpEntryPoint' : 15, - 'OpExecutionMode' : 16, - 'OpCapability' : 17, - 'OpTypeVoid' : 19, - 'OpTypeBool' : 20, - 'OpTypeInt' : 21, - 'OpTypeFloat' : 22, - 'OpTypeVector' : 23, - 'OpTypeMatrix' : 24, - 'OpTypeImage' : 25, - 'OpTypeSampler' : 26, - 'OpTypeSampledImage' : 27, - 'OpTypeArray' : 28, - 'OpTypeRuntimeArray' : 29, - 'OpTypeStruct' : 30, - 'OpTypeOpaque' : 31, - 'OpTypePointer' : 32, - 'OpTypeFunction' : 33, - 'OpTypeEvent' : 34, - 'OpTypeDeviceEvent' : 35, - 'OpTypeReserveId' : 36, - 'OpTypeQueue' : 37, - 'OpTypePipe' : 38, - 'OpTypeForwardPointer' : 39, - 'OpConstantTrue' : 41, - 'OpConstantFalse' : 42, - 'OpConstant' : 43, - 'OpConstantComposite' : 44, - 'OpConstantSampler' : 45, - 'OpConstantNull' : 46, - 'OpSpecConstantTrue' : 48, - 'OpSpecConstantFalse' : 49, - 'OpSpecConstant' : 50, - 'OpSpecConstantComposite' : 51, - 'OpSpecConstantOp' : 52, - 'OpFunction' : 54, - 'OpFunctionParameter' : 55, - 'OpFunctionEnd' : 56, - 'OpFunctionCall' : 57, - 'OpVariable' : 59, - 'OpImageTexelPointer' : 60, - 'OpLoad' : 61, - 'OpStore' : 62, - 'OpCopyMemory' : 63, - 'OpCopyMemorySized' : 64, - 'OpAccessChain' : 65, - 'OpInBoundsAccessChain' : 66, - 'OpPtrAccessChain' : 67, - 'OpArrayLength' : 68, - 'OpGenericPtrMemSemantics' : 69, - 'OpInBoundsPtrAccessChain' : 70, - 'OpDecorate' : 71, - 'OpMemberDecorate' : 72, - 'OpDecorationGroup' : 73, - 'OpGroupDecorate' : 74, - 'OpGroupMemberDecorate' : 75, - 'OpVectorExtractDynamic' : 77, - 'OpVectorInsertDynamic' : 78, - 'OpVectorShuffle' : 79, - 'OpCompositeConstruct' : 80, - 'OpCompositeExtract' : 81, - 'OpCompositeInsert' : 82, - 'OpCopyObject' : 83, - 'OpTranspose' : 84, - 'OpSampledImage' : 86, - 'OpImageSampleImplicitLod' : 87, - 'OpImageSampleExplicitLod' : 88, - 'OpImageSampleDrefImplicitLod' : 89, - 'OpImageSampleDrefExplicitLod' : 90, - 'OpImageSampleProjImplicitLod' : 91, - 'OpImageSampleProjExplicitLod' : 92, - 'OpImageSampleProjDrefImplicitLod' : 93, - 'OpImageSampleProjDrefExplicitLod' : 94, - 'OpImageFetch' : 95, - 'OpImageGather' : 96, - 'OpImageDrefGather' : 97, - 'OpImageRead' : 98, - 'OpImageWrite' : 99, - 'OpImage' : 100, - 'OpImageQueryFormat' : 101, - 'OpImageQueryOrder' : 102, - 'OpImageQuerySizeLod' : 103, - 'OpImageQuerySize' : 104, - 'OpImageQueryLod' : 105, - 'OpImageQueryLevels' : 106, - 'OpImageQuerySamples' : 107, - 'OpConvertFToU' : 109, - 'OpConvertFToS' : 110, - 'OpConvertSToF' : 111, - 'OpConvertUToF' : 112, - 'OpUConvert' : 113, - 'OpSConvert' : 114, - 'OpFConvert' : 115, - 'OpQuantizeToF16' : 116, - 'OpConvertPtrToU' : 117, - 'OpSatConvertSToU' : 118, - 'OpSatConvertUToS' : 119, - 'OpConvertUToPtr' : 120, - 'OpPtrCastToGeneric' : 121, - 'OpGenericCastToPtr' : 122, - 'OpGenericCastToPtrExplicit' : 123, - 'OpBitcast' : 124, - 'OpSNegate' : 126, - 'OpFNegate' : 127, - 'OpIAdd' : 128, - 'OpFAdd' : 129, - 'OpISub' : 130, - 'OpFSub' : 131, - 'OpIMul' : 132, - 'OpFMul' : 133, - 'OpUDiv' : 134, - 'OpSDiv' : 135, - 'OpFDiv' : 136, - 'OpUMod' : 137, - 'OpSRem' : 138, - 'OpSMod' : 139, - 'OpFRem' : 140, - 'OpFMod' : 141, - 'OpVectorTimesScalar' : 142, - 'OpMatrixTimesScalar' : 143, - 'OpVectorTimesMatrix' : 144, - 'OpMatrixTimesVector' : 145, - 'OpMatrixTimesMatrix' : 146, - 'OpOuterProduct' : 147, - 'OpDot' : 148, - 'OpIAddCarry' : 149, - 'OpISubBorrow' : 150, - 'OpUMulExtended' : 151, - 'OpSMulExtended' : 152, - 'OpAny' : 154, - 'OpAll' : 155, - 'OpIsNan' : 156, - 'OpIsInf' : 157, - 'OpIsFinite' : 158, - 'OpIsNormal' : 159, - 'OpSignBitSet' : 160, - 'OpLessOrGreater' : 161, - 'OpOrdered' : 162, - 'OpUnordered' : 163, - 'OpLogicalEqual' : 164, - 'OpLogicalNotEqual' : 165, - 'OpLogicalOr' : 166, - 'OpLogicalAnd' : 167, - 'OpLogicalNot' : 168, - 'OpSelect' : 169, - 'OpIEqual' : 170, - 'OpINotEqual' : 171, - 'OpUGreaterThan' : 172, - 'OpSGreaterThan' : 173, - 'OpUGreaterThanEqual' : 174, - 'OpSGreaterThanEqual' : 175, - 'OpULessThan' : 176, - 'OpSLessThan' : 177, - 'OpULessThanEqual' : 178, - 'OpSLessThanEqual' : 179, - 'OpFOrdEqual' : 180, - 'OpFUnordEqual' : 181, - 'OpFOrdNotEqual' : 182, - 'OpFUnordNotEqual' : 183, - 'OpFOrdLessThan' : 184, - 'OpFUnordLessThan' : 185, - 'OpFOrdGreaterThan' : 186, - 'OpFUnordGreaterThan' : 187, - 'OpFOrdLessThanEqual' : 188, - 'OpFUnordLessThanEqual' : 189, - 'OpFOrdGreaterThanEqual' : 190, - 'OpFUnordGreaterThanEqual' : 191, - 'OpShiftRightLogical' : 194, - 'OpShiftRightArithmetic' : 195, - 'OpShiftLeftLogical' : 196, - 'OpBitwiseOr' : 197, - 'OpBitwiseXor' : 198, - 'OpBitwiseAnd' : 199, - 'OpNot' : 200, - 'OpBitFieldInsert' : 201, - 'OpBitFieldSExtract' : 202, - 'OpBitFieldUExtract' : 203, - 'OpBitReverse' : 204, - 'OpBitCount' : 205, - 'OpDPdx' : 207, - 'OpDPdy' : 208, - 'OpFwidth' : 209, - 'OpDPdxFine' : 210, - 'OpDPdyFine' : 211, - 'OpFwidthFine' : 212, - 'OpDPdxCoarse' : 213, - 'OpDPdyCoarse' : 214, - 'OpFwidthCoarse' : 215, - 'OpEmitVertex' : 218, - 'OpEndPrimitive' : 219, - 'OpEmitStreamVertex' : 220, - 'OpEndStreamPrimitive' : 221, - 'OpControlBarrier' : 224, - 'OpMemoryBarrier' : 225, - 'OpAtomicLoad' : 227, - 'OpAtomicStore' : 228, - 'OpAtomicExchange' : 229, - 'OpAtomicCompareExchange' : 230, - 'OpAtomicCompareExchangeWeak' : 231, - 'OpAtomicIIncrement' : 232, - 'OpAtomicIDecrement' : 233, - 'OpAtomicIAdd' : 234, - 'OpAtomicISub' : 235, - 'OpAtomicSMin' : 236, - 'OpAtomicUMin' : 237, - 'OpAtomicSMax' : 238, - 'OpAtomicUMax' : 239, - 'OpAtomicAnd' : 240, - 'OpAtomicOr' : 241, - 'OpAtomicXor' : 242, - 'OpPhi' : 245, - 'OpLoopMerge' : 246, - 'OpSelectionMerge' : 247, - 'OpLabel' : 248, - 'OpBranch' : 249, - 'OpBranchConditional' : 250, - 'OpSwitch' : 251, - 'OpKill' : 252, - 'OpReturn' : 253, - 'OpReturnValue' : 254, - 'OpUnreachable' : 255, - 'OpLifetimeStart' : 256, - 'OpLifetimeStop' : 257, - 'OpGroupAsyncCopy' : 259, - 'OpGroupWaitEvents' : 260, - 'OpGroupAll' : 261, - 'OpGroupAny' : 262, - 'OpGroupBroadcast' : 263, - 'OpGroupIAdd' : 264, - 'OpGroupFAdd' : 265, - 'OpGroupFMin' : 266, - 'OpGroupUMin' : 267, - 'OpGroupSMin' : 268, - 'OpGroupFMax' : 269, - 'OpGroupUMax' : 270, - 'OpGroupSMax' : 271, - 'OpReadPipe' : 274, - 'OpWritePipe' : 275, - 'OpReservedReadPipe' : 276, - 'OpReservedWritePipe' : 277, - 'OpReserveReadPipePackets' : 278, - 'OpReserveWritePipePackets' : 279, - 'OpCommitReadPipe' : 280, - 'OpCommitWritePipe' : 281, - 'OpIsValidReserveId' : 282, - 'OpGetNumPipePackets' : 283, - 'OpGetMaxPipePackets' : 284, - 'OpGroupReserveReadPipePackets' : 285, - 'OpGroupReserveWritePipePackets' : 286, - 'OpGroupCommitReadPipe' : 287, - 'OpGroupCommitWritePipe' : 288, - 'OpEnqueueMarker' : 291, - 'OpEnqueueKernel' : 292, - 'OpGetKernelNDrangeSubGroupCount' : 293, - 'OpGetKernelNDrangeMaxSubGroupSize' : 294, - 'OpGetKernelWorkGroupSize' : 295, - 'OpGetKernelPreferredWorkGroupSizeMultiple' : 296, - 'OpRetainEvent' : 297, - 'OpReleaseEvent' : 298, - 'OpCreateUserEvent' : 299, - 'OpIsValidEvent' : 300, - 'OpSetUserEventStatus' : 301, - 'OpCaptureEventProfilingInfo' : 302, - 'OpGetDefaultQueue' : 303, - 'OpBuildNDRange' : 304, - 'OpImageSparseSampleImplicitLod' : 305, - 'OpImageSparseSampleExplicitLod' : 306, - 'OpImageSparseSampleDrefImplicitLod' : 307, - 'OpImageSparseSampleDrefExplicitLod' : 308, - 'OpImageSparseSampleProjImplicitLod' : 309, - 'OpImageSparseSampleProjExplicitLod' : 310, - 'OpImageSparseSampleProjDrefImplicitLod' : 311, - 'OpImageSparseSampleProjDrefExplicitLod' : 312, - 'OpImageSparseFetch' : 313, - 'OpImageSparseGather' : 314, - 'OpImageSparseDrefGather' : 315, - 'OpImageSparseTexelsResident' : 316, - 'OpNoLine' : 317, - 'OpAtomicFlagTestAndSet' : 318, - 'OpAtomicFlagClear' : 319, - 'OpImageSparseRead' : 320, - 'OpSizeOf' : 321, - 'OpTypePipeStorage' : 322, - 'OpConstantPipeStorage' : 323, - 'OpCreatePipeFromPipeStorage' : 324, - 'OpGetKernelLocalSizeForSubgroupCount' : 325, - 'OpGetKernelMaxNumSubgroups' : 326, - 'OpTypeNamedBarrier' : 327, - 'OpNamedBarrierInitialize' : 328, - 'OpMemoryNamedBarrier' : 329, - 'OpModuleProcessed' : 330, - 'OpSubgroupBallotKHR' : 4421, - 'OpSubgroupFirstInvocationKHR' : 4422, - 'OpSubgroupAllKHR' : 4428, - 'OpSubgroupAnyKHR' : 4429, - 'OpSubgroupAllEqualKHR' : 4430, - 'OpSubgroupReadInvocationKHR' : 4432, - }, - -} - +# Copyright (c) 2014-2017 The Khronos Group Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and/or associated documentation files (the "Materials"), +# to deal in the Materials without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Materials, and to permit persons to whom the +# Materials are furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Materials. +# +# MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +# STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +# HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +# +# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +# IN THE MATERIALS. + +# This header is automatically generated by the same tool that creates +# the Binary Section of the SPIR-V specification. + +# Enumeration tokens for SPIR-V, in various styles: +# C, C++, C++11, JSON, Lua, Python +# +# - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +# - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +# - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +# - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +# - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +# +# Some tokens act like mask values, which can be OR'd together, +# while others are mutually exclusive. The mask-like ones have +# "Mask" in their name, and a parallel enum that has the shift +# amount (1 << x) for each corresponding enumerant. + +spv = { + 'MagicNumber' : 0x07230203, + 'Version' : 0x00010100, + 'Revision' : 8, + 'OpCodeMask' : 0xffff, + 'WordCountShift' : 16, + + 'SourceLanguage' : { + 'Unknown' : 0, + 'ESSL' : 1, + 'GLSL' : 2, + 'OpenCL_C' : 3, + 'OpenCL_CPP' : 4, + 'HLSL' : 5, + }, + + 'ExecutionModel' : { + 'Vertex' : 0, + 'TessellationControl' : 1, + 'TessellationEvaluation' : 2, + 'Geometry' : 3, + 'Fragment' : 4, + 'GLCompute' : 5, + 'Kernel' : 6, + }, + + 'AddressingModel' : { + 'Logical' : 0, + 'Physical32' : 1, + 'Physical64' : 2, + }, + + 'MemoryModel' : { + 'Simple' : 0, + 'GLSL450' : 1, + 'OpenCL' : 2, + }, + + 'ExecutionMode' : { + 'Invocations' : 0, + 'SpacingEqual' : 1, + 'SpacingFractionalEven' : 2, + 'SpacingFractionalOdd' : 3, + 'VertexOrderCw' : 4, + 'VertexOrderCcw' : 5, + 'PixelCenterInteger' : 6, + 'OriginUpperLeft' : 7, + 'OriginLowerLeft' : 8, + 'EarlyFragmentTests' : 9, + 'PointMode' : 10, + 'Xfb' : 11, + 'DepthReplacing' : 12, + 'DepthGreater' : 14, + 'DepthLess' : 15, + 'DepthUnchanged' : 16, + 'LocalSize' : 17, + 'LocalSizeHint' : 18, + 'InputPoints' : 19, + 'InputLines' : 20, + 'InputLinesAdjacency' : 21, + 'Triangles' : 22, + 'InputTrianglesAdjacency' : 23, + 'Quads' : 24, + 'Isolines' : 25, + 'OutputVertices' : 26, + 'OutputPoints' : 27, + 'OutputLineStrip' : 28, + 'OutputTriangleStrip' : 29, + 'VecTypeHint' : 30, + 'ContractionOff' : 31, + 'Initializer' : 33, + 'Finalizer' : 34, + 'SubgroupSize' : 35, + 'SubgroupsPerWorkgroup' : 36, + 'PostDepthCoverage' : 4446, + 'StencilRefReplacingEXT' : 5027, + }, + + 'StorageClass' : { + 'UniformConstant' : 0, + 'Input' : 1, + 'Uniform' : 2, + 'Output' : 3, + 'Workgroup' : 4, + 'CrossWorkgroup' : 5, + 'Private' : 6, + 'Function' : 7, + 'Generic' : 8, + 'PushConstant' : 9, + 'AtomicCounter' : 10, + 'Image' : 11, + 'StorageBuffer' : 12, + }, + + 'Dim' : { + 'Dim1D' : 0, + 'Dim2D' : 1, + 'Dim3D' : 2, + 'Cube' : 3, + 'Rect' : 4, + 'Buffer' : 5, + 'SubpassData' : 6, + }, + + 'SamplerAddressingMode' : { + 'None' : 0, + 'ClampToEdge' : 1, + 'Clamp' : 2, + 'Repeat' : 3, + 'RepeatMirrored' : 4, + }, + + 'SamplerFilterMode' : { + 'Nearest' : 0, + 'Linear' : 1, + }, + + 'ImageFormat' : { + 'Unknown' : 0, + 'Rgba32f' : 1, + 'Rgba16f' : 2, + 'R32f' : 3, + 'Rgba8' : 4, + 'Rgba8Snorm' : 5, + 'Rg32f' : 6, + 'Rg16f' : 7, + 'R11fG11fB10f' : 8, + 'R16f' : 9, + 'Rgba16' : 10, + 'Rgb10A2' : 11, + 'Rg16' : 12, + 'Rg8' : 13, + 'R16' : 14, + 'R8' : 15, + 'Rgba16Snorm' : 16, + 'Rg16Snorm' : 17, + 'Rg8Snorm' : 18, + 'R16Snorm' : 19, + 'R8Snorm' : 20, + 'Rgba32i' : 21, + 'Rgba16i' : 22, + 'Rgba8i' : 23, + 'R32i' : 24, + 'Rg32i' : 25, + 'Rg16i' : 26, + 'Rg8i' : 27, + 'R16i' : 28, + 'R8i' : 29, + 'Rgba32ui' : 30, + 'Rgba16ui' : 31, + 'Rgba8ui' : 32, + 'R32ui' : 33, + 'Rgb10a2ui' : 34, + 'Rg32ui' : 35, + 'Rg16ui' : 36, + 'Rg8ui' : 37, + 'R16ui' : 38, + 'R8ui' : 39, + }, + + 'ImageChannelOrder' : { + 'R' : 0, + 'A' : 1, + 'RG' : 2, + 'RA' : 3, + 'RGB' : 4, + 'RGBA' : 5, + 'BGRA' : 6, + 'ARGB' : 7, + 'Intensity' : 8, + 'Luminance' : 9, + 'Rx' : 10, + 'RGx' : 11, + 'RGBx' : 12, + 'Depth' : 13, + 'DepthStencil' : 14, + 'sRGB' : 15, + 'sRGBx' : 16, + 'sRGBA' : 17, + 'sBGRA' : 18, + 'ABGR' : 19, + }, + + 'ImageChannelDataType' : { + 'SnormInt8' : 0, + 'SnormInt16' : 1, + 'UnormInt8' : 2, + 'UnormInt16' : 3, + 'UnormShort565' : 4, + 'UnormShort555' : 5, + 'UnormInt101010' : 6, + 'SignedInt8' : 7, + 'SignedInt16' : 8, + 'SignedInt32' : 9, + 'UnsignedInt8' : 10, + 'UnsignedInt16' : 11, + 'UnsignedInt32' : 12, + 'HalfFloat' : 13, + 'Float' : 14, + 'UnormInt24' : 15, + 'UnormInt101010_2' : 16, + }, + + 'ImageOperandsShift' : { + 'Bias' : 0, + 'Lod' : 1, + 'Grad' : 2, + 'ConstOffset' : 3, + 'Offset' : 4, + 'ConstOffsets' : 5, + 'Sample' : 6, + 'MinLod' : 7, + }, + + 'ImageOperandsMask' : { + 'MaskNone' : 0, + 'Bias' : 0x00000001, + 'Lod' : 0x00000002, + 'Grad' : 0x00000004, + 'ConstOffset' : 0x00000008, + 'Offset' : 0x00000010, + 'ConstOffsets' : 0x00000020, + 'Sample' : 0x00000040, + 'MinLod' : 0x00000080, + }, + + 'FPFastMathModeShift' : { + 'NotNaN' : 0, + 'NotInf' : 1, + 'NSZ' : 2, + 'AllowRecip' : 3, + 'Fast' : 4, + }, + + 'FPFastMathModeMask' : { + 'MaskNone' : 0, + 'NotNaN' : 0x00000001, + 'NotInf' : 0x00000002, + 'NSZ' : 0x00000004, + 'AllowRecip' : 0x00000008, + 'Fast' : 0x00000010, + }, + + 'FPRoundingMode' : { + 'RTE' : 0, + 'RTZ' : 1, + 'RTP' : 2, + 'RTN' : 3, + }, + + 'LinkageType' : { + 'Export' : 0, + 'Import' : 1, + }, + + 'AccessQualifier' : { + 'ReadOnly' : 0, + 'WriteOnly' : 1, + 'ReadWrite' : 2, + }, + + 'FunctionParameterAttribute' : { + 'Zext' : 0, + 'Sext' : 1, + 'ByVal' : 2, + 'Sret' : 3, + 'NoAlias' : 4, + 'NoCapture' : 5, + 'NoWrite' : 6, + 'NoReadWrite' : 7, + }, + + 'Decoration' : { + 'RelaxedPrecision' : 0, + 'SpecId' : 1, + 'Block' : 2, + 'BufferBlock' : 3, + 'RowMajor' : 4, + 'ColMajor' : 5, + 'ArrayStride' : 6, + 'MatrixStride' : 7, + 'GLSLShared' : 8, + 'GLSLPacked' : 9, + 'CPacked' : 10, + 'BuiltIn' : 11, + 'NoPerspective' : 13, + 'Flat' : 14, + 'Patch' : 15, + 'Centroid' : 16, + 'Sample' : 17, + 'Invariant' : 18, + 'Restrict' : 19, + 'Aliased' : 20, + 'Volatile' : 21, + 'Constant' : 22, + 'Coherent' : 23, + 'NonWritable' : 24, + 'NonReadable' : 25, + 'Uniform' : 26, + 'SaturatedConversion' : 28, + 'Stream' : 29, + 'Location' : 30, + 'Component' : 31, + 'Index' : 32, + 'Binding' : 33, + 'DescriptorSet' : 34, + 'Offset' : 35, + 'XfbBuffer' : 36, + 'XfbStride' : 37, + 'FuncParamAttr' : 38, + 'FPRoundingMode' : 39, + 'FPFastMathMode' : 40, + 'LinkageAttributes' : 41, + 'NoContraction' : 42, + 'InputAttachmentIndex' : 43, + 'Alignment' : 44, + 'MaxByteOffset' : 45, + 'ExplicitInterpAMD' : 4999, + 'OverrideCoverageNV' : 5248, + 'PassthroughNV' : 5250, + 'ViewportRelativeNV' : 5252, + 'SecondaryViewportRelativeNV' : 5256, + }, + + 'BuiltIn' : { + 'Position' : 0, + 'PointSize' : 1, + 'ClipDistance' : 3, + 'CullDistance' : 4, + 'VertexId' : 5, + 'InstanceId' : 6, + 'PrimitiveId' : 7, + 'InvocationId' : 8, + 'Layer' : 9, + 'ViewportIndex' : 10, + 'TessLevelOuter' : 11, + 'TessLevelInner' : 12, + 'TessCoord' : 13, + 'PatchVertices' : 14, + 'FragCoord' : 15, + 'PointCoord' : 16, + 'FrontFacing' : 17, + 'SampleId' : 18, + 'SamplePosition' : 19, + 'SampleMask' : 20, + 'FragDepth' : 22, + 'HelperInvocation' : 23, + 'NumWorkgroups' : 24, + 'WorkgroupSize' : 25, + 'WorkgroupId' : 26, + 'LocalInvocationId' : 27, + 'GlobalInvocationId' : 28, + 'LocalInvocationIndex' : 29, + 'WorkDim' : 30, + 'GlobalSize' : 31, + 'EnqueuedWorkgroupSize' : 32, + 'GlobalOffset' : 33, + 'GlobalLinearId' : 34, + 'SubgroupSize' : 36, + 'SubgroupMaxSize' : 37, + 'NumSubgroups' : 38, + 'NumEnqueuedSubgroups' : 39, + 'SubgroupId' : 40, + 'SubgroupLocalInvocationId' : 41, + 'VertexIndex' : 42, + 'InstanceIndex' : 43, + 'SubgroupEqMaskKHR' : 4416, + 'SubgroupGeMaskKHR' : 4417, + 'SubgroupGtMaskKHR' : 4418, + 'SubgroupLeMaskKHR' : 4419, + 'SubgroupLtMaskKHR' : 4420, + 'BaseVertex' : 4424, + 'BaseInstance' : 4425, + 'DrawIndex' : 4426, + 'DeviceIndex' : 4438, + 'ViewIndex' : 4440, + 'BaryCoordNoPerspAMD' : 4992, + 'BaryCoordNoPerspCentroidAMD' : 4993, + 'BaryCoordNoPerspSampleAMD' : 4994, + 'BaryCoordSmoothAMD' : 4995, + 'BaryCoordSmoothCentroidAMD' : 4996, + 'BaryCoordSmoothSampleAMD' : 4997, + 'BaryCoordPullModelAMD' : 4998, + 'FragStencilRefEXT' : 5014, + 'ViewportMaskNV' : 5253, + 'SecondaryPositionNV' : 5257, + 'SecondaryViewportMaskNV' : 5258, + 'PositionPerViewNV' : 5261, + 'ViewportMaskPerViewNV' : 5262, + }, + + 'SelectionControlShift' : { + 'Flatten' : 0, + 'DontFlatten' : 1, + }, + + 'SelectionControlMask' : { + 'MaskNone' : 0, + 'Flatten' : 0x00000001, + 'DontFlatten' : 0x00000002, + }, + + 'LoopControlShift' : { + 'Unroll' : 0, + 'DontUnroll' : 1, + 'DependencyInfinite' : 2, + 'DependencyLength' : 3, + }, + + 'LoopControlMask' : { + 'MaskNone' : 0, + 'Unroll' : 0x00000001, + 'DontUnroll' : 0x00000002, + 'DependencyInfinite' : 0x00000004, + 'DependencyLength' : 0x00000008, + }, + + 'FunctionControlShift' : { + 'Inline' : 0, + 'DontInline' : 1, + 'Pure' : 2, + 'Const' : 3, + }, + + 'FunctionControlMask' : { + 'MaskNone' : 0, + 'Inline' : 0x00000001, + 'DontInline' : 0x00000002, + 'Pure' : 0x00000004, + 'Const' : 0x00000008, + }, + + 'MemorySemanticsShift' : { + 'Acquire' : 1, + 'Release' : 2, + 'AcquireRelease' : 3, + 'SequentiallyConsistent' : 4, + 'UniformMemory' : 6, + 'SubgroupMemory' : 7, + 'WorkgroupMemory' : 8, + 'CrossWorkgroupMemory' : 9, + 'AtomicCounterMemory' : 10, + 'ImageMemory' : 11, + }, + + 'MemorySemanticsMask' : { + 'MaskNone' : 0, + 'Acquire' : 0x00000002, + 'Release' : 0x00000004, + 'AcquireRelease' : 0x00000008, + 'SequentiallyConsistent' : 0x00000010, + 'UniformMemory' : 0x00000040, + 'SubgroupMemory' : 0x00000080, + 'WorkgroupMemory' : 0x00000100, + 'CrossWorkgroupMemory' : 0x00000200, + 'AtomicCounterMemory' : 0x00000400, + 'ImageMemory' : 0x00000800, + }, + + 'MemoryAccessShift' : { + 'Volatile' : 0, + 'Aligned' : 1, + 'Nontemporal' : 2, + }, + + 'MemoryAccessMask' : { + 'MaskNone' : 0, + 'Volatile' : 0x00000001, + 'Aligned' : 0x00000002, + 'Nontemporal' : 0x00000004, + }, + + 'Scope' : { + 'CrossDevice' : 0, + 'Device' : 1, + 'Workgroup' : 2, + 'Subgroup' : 3, + 'Invocation' : 4, + }, + + 'GroupOperation' : { + 'Reduce' : 0, + 'InclusiveScan' : 1, + 'ExclusiveScan' : 2, + }, + + 'KernelEnqueueFlags' : { + 'NoWait' : 0, + 'WaitKernel' : 1, + 'WaitWorkGroup' : 2, + }, + + 'KernelProfilingInfoShift' : { + 'CmdExecTime' : 0, + }, + + 'KernelProfilingInfoMask' : { + 'MaskNone' : 0, + 'CmdExecTime' : 0x00000001, + }, + + 'Capability' : { + 'Matrix' : 0, + 'Shader' : 1, + 'Geometry' : 2, + 'Tessellation' : 3, + 'Addresses' : 4, + 'Linkage' : 5, + 'Kernel' : 6, + 'Vector16' : 7, + 'Float16Buffer' : 8, + 'Float16' : 9, + 'Float64' : 10, + 'Int64' : 11, + 'Int64Atomics' : 12, + 'ImageBasic' : 13, + 'ImageReadWrite' : 14, + 'ImageMipmap' : 15, + 'Pipes' : 17, + 'Groups' : 18, + 'DeviceEnqueue' : 19, + 'LiteralSampler' : 20, + 'AtomicStorage' : 21, + 'Int16' : 22, + 'TessellationPointSize' : 23, + 'GeometryPointSize' : 24, + 'ImageGatherExtended' : 25, + 'StorageImageMultisample' : 27, + 'UniformBufferArrayDynamicIndexing' : 28, + 'SampledImageArrayDynamicIndexing' : 29, + 'StorageBufferArrayDynamicIndexing' : 30, + 'StorageImageArrayDynamicIndexing' : 31, + 'ClipDistance' : 32, + 'CullDistance' : 33, + 'ImageCubeArray' : 34, + 'SampleRateShading' : 35, + 'ImageRect' : 36, + 'SampledRect' : 37, + 'GenericPointer' : 38, + 'Int8' : 39, + 'InputAttachment' : 40, + 'SparseResidency' : 41, + 'MinLod' : 42, + 'Sampled1D' : 43, + 'Image1D' : 44, + 'SampledCubeArray' : 45, + 'SampledBuffer' : 46, + 'ImageBuffer' : 47, + 'ImageMSArray' : 48, + 'StorageImageExtendedFormats' : 49, + 'ImageQuery' : 50, + 'DerivativeControl' : 51, + 'InterpolationFunction' : 52, + 'TransformFeedback' : 53, + 'GeometryStreams' : 54, + 'StorageImageReadWithoutFormat' : 55, + 'StorageImageWriteWithoutFormat' : 56, + 'MultiViewport' : 57, + 'SubgroupDispatch' : 58, + 'NamedBarrier' : 59, + 'PipeStorage' : 60, + 'SubgroupBallotKHR' : 4423, + 'DrawParameters' : 4427, + 'SubgroupVoteKHR' : 4431, + 'StorageBuffer16BitAccess' : 4433, + 'StorageUniformBufferBlock16' : 4433, + 'StorageUniform16' : 4434, + 'UniformAndStorageBuffer16BitAccess' : 4434, + 'StoragePushConstant16' : 4435, + 'StorageInputOutput16' : 4436, + 'DeviceGroup' : 4437, + 'MultiView' : 4439, + 'VariablePointersStorageBuffer' : 4441, + 'VariablePointers' : 4442, + 'AtomicStorageOps' : 4445, + 'SampleMaskPostDepthCoverage' : 4447, + 'ImageGatherBiasLodAMD' : 5009, + 'FragmentMaskAMD' : 5010, + 'StencilExportEXT' : 5013, + 'ImageReadWriteLodAMD' : 5015, + 'SampleMaskOverrideCoverageNV' : 5249, + 'GeometryShaderPassthroughNV' : 5251, + 'ShaderViewportIndexLayerEXT' : 5254, + 'ShaderViewportIndexLayerNV' : 5254, + 'ShaderViewportMaskNV' : 5255, + 'ShaderStereoViewNV' : 5259, + 'PerViewAttributesNV' : 5260, + 'SubgroupShuffleINTEL' : 5568, + 'SubgroupBufferBlockIOINTEL' : 5569, + 'SubgroupImageBlockIOINTEL' : 5570, + }, + + 'Op' : { + 'OpNop' : 0, + 'OpUndef' : 1, + 'OpSourceContinued' : 2, + 'OpSource' : 3, + 'OpSourceExtension' : 4, + 'OpName' : 5, + 'OpMemberName' : 6, + 'OpString' : 7, + 'OpLine' : 8, + 'OpExtension' : 10, + 'OpExtInstImport' : 11, + 'OpExtInst' : 12, + 'OpMemoryModel' : 14, + 'OpEntryPoint' : 15, + 'OpExecutionMode' : 16, + 'OpCapability' : 17, + 'OpTypeVoid' : 19, + 'OpTypeBool' : 20, + 'OpTypeInt' : 21, + 'OpTypeFloat' : 22, + 'OpTypeVector' : 23, + 'OpTypeMatrix' : 24, + 'OpTypeImage' : 25, + 'OpTypeSampler' : 26, + 'OpTypeSampledImage' : 27, + 'OpTypeArray' : 28, + 'OpTypeRuntimeArray' : 29, + 'OpTypeStruct' : 30, + 'OpTypeOpaque' : 31, + 'OpTypePointer' : 32, + 'OpTypeFunction' : 33, + 'OpTypeEvent' : 34, + 'OpTypeDeviceEvent' : 35, + 'OpTypeReserveId' : 36, + 'OpTypeQueue' : 37, + 'OpTypePipe' : 38, + 'OpTypeForwardPointer' : 39, + 'OpConstantTrue' : 41, + 'OpConstantFalse' : 42, + 'OpConstant' : 43, + 'OpConstantComposite' : 44, + 'OpConstantSampler' : 45, + 'OpConstantNull' : 46, + 'OpSpecConstantTrue' : 48, + 'OpSpecConstantFalse' : 49, + 'OpSpecConstant' : 50, + 'OpSpecConstantComposite' : 51, + 'OpSpecConstantOp' : 52, + 'OpFunction' : 54, + 'OpFunctionParameter' : 55, + 'OpFunctionEnd' : 56, + 'OpFunctionCall' : 57, + 'OpVariable' : 59, + 'OpImageTexelPointer' : 60, + 'OpLoad' : 61, + 'OpStore' : 62, + 'OpCopyMemory' : 63, + 'OpCopyMemorySized' : 64, + 'OpAccessChain' : 65, + 'OpInBoundsAccessChain' : 66, + 'OpPtrAccessChain' : 67, + 'OpArrayLength' : 68, + 'OpGenericPtrMemSemantics' : 69, + 'OpInBoundsPtrAccessChain' : 70, + 'OpDecorate' : 71, + 'OpMemberDecorate' : 72, + 'OpDecorationGroup' : 73, + 'OpGroupDecorate' : 74, + 'OpGroupMemberDecorate' : 75, + 'OpVectorExtractDynamic' : 77, + 'OpVectorInsertDynamic' : 78, + 'OpVectorShuffle' : 79, + 'OpCompositeConstruct' : 80, + 'OpCompositeExtract' : 81, + 'OpCompositeInsert' : 82, + 'OpCopyObject' : 83, + 'OpTranspose' : 84, + 'OpSampledImage' : 86, + 'OpImageSampleImplicitLod' : 87, + 'OpImageSampleExplicitLod' : 88, + 'OpImageSampleDrefImplicitLod' : 89, + 'OpImageSampleDrefExplicitLod' : 90, + 'OpImageSampleProjImplicitLod' : 91, + 'OpImageSampleProjExplicitLod' : 92, + 'OpImageSampleProjDrefImplicitLod' : 93, + 'OpImageSampleProjDrefExplicitLod' : 94, + 'OpImageFetch' : 95, + 'OpImageGather' : 96, + 'OpImageDrefGather' : 97, + 'OpImageRead' : 98, + 'OpImageWrite' : 99, + 'OpImage' : 100, + 'OpImageQueryFormat' : 101, + 'OpImageQueryOrder' : 102, + 'OpImageQuerySizeLod' : 103, + 'OpImageQuerySize' : 104, + 'OpImageQueryLod' : 105, + 'OpImageQueryLevels' : 106, + 'OpImageQuerySamples' : 107, + 'OpConvertFToU' : 109, + 'OpConvertFToS' : 110, + 'OpConvertSToF' : 111, + 'OpConvertUToF' : 112, + 'OpUConvert' : 113, + 'OpSConvert' : 114, + 'OpFConvert' : 115, + 'OpQuantizeToF16' : 116, + 'OpConvertPtrToU' : 117, + 'OpSatConvertSToU' : 118, + 'OpSatConvertUToS' : 119, + 'OpConvertUToPtr' : 120, + 'OpPtrCastToGeneric' : 121, + 'OpGenericCastToPtr' : 122, + 'OpGenericCastToPtrExplicit' : 123, + 'OpBitcast' : 124, + 'OpSNegate' : 126, + 'OpFNegate' : 127, + 'OpIAdd' : 128, + 'OpFAdd' : 129, + 'OpISub' : 130, + 'OpFSub' : 131, + 'OpIMul' : 132, + 'OpFMul' : 133, + 'OpUDiv' : 134, + 'OpSDiv' : 135, + 'OpFDiv' : 136, + 'OpUMod' : 137, + 'OpSRem' : 138, + 'OpSMod' : 139, + 'OpFRem' : 140, + 'OpFMod' : 141, + 'OpVectorTimesScalar' : 142, + 'OpMatrixTimesScalar' : 143, + 'OpVectorTimesMatrix' : 144, + 'OpMatrixTimesVector' : 145, + 'OpMatrixTimesMatrix' : 146, + 'OpOuterProduct' : 147, + 'OpDot' : 148, + 'OpIAddCarry' : 149, + 'OpISubBorrow' : 150, + 'OpUMulExtended' : 151, + 'OpSMulExtended' : 152, + 'OpAny' : 154, + 'OpAll' : 155, + 'OpIsNan' : 156, + 'OpIsInf' : 157, + 'OpIsFinite' : 158, + 'OpIsNormal' : 159, + 'OpSignBitSet' : 160, + 'OpLessOrGreater' : 161, + 'OpOrdered' : 162, + 'OpUnordered' : 163, + 'OpLogicalEqual' : 164, + 'OpLogicalNotEqual' : 165, + 'OpLogicalOr' : 166, + 'OpLogicalAnd' : 167, + 'OpLogicalNot' : 168, + 'OpSelect' : 169, + 'OpIEqual' : 170, + 'OpINotEqual' : 171, + 'OpUGreaterThan' : 172, + 'OpSGreaterThan' : 173, + 'OpUGreaterThanEqual' : 174, + 'OpSGreaterThanEqual' : 175, + 'OpULessThan' : 176, + 'OpSLessThan' : 177, + 'OpULessThanEqual' : 178, + 'OpSLessThanEqual' : 179, + 'OpFOrdEqual' : 180, + 'OpFUnordEqual' : 181, + 'OpFOrdNotEqual' : 182, + 'OpFUnordNotEqual' : 183, + 'OpFOrdLessThan' : 184, + 'OpFUnordLessThan' : 185, + 'OpFOrdGreaterThan' : 186, + 'OpFUnordGreaterThan' : 187, + 'OpFOrdLessThanEqual' : 188, + 'OpFUnordLessThanEqual' : 189, + 'OpFOrdGreaterThanEqual' : 190, + 'OpFUnordGreaterThanEqual' : 191, + 'OpShiftRightLogical' : 194, + 'OpShiftRightArithmetic' : 195, + 'OpShiftLeftLogical' : 196, + 'OpBitwiseOr' : 197, + 'OpBitwiseXor' : 198, + 'OpBitwiseAnd' : 199, + 'OpNot' : 200, + 'OpBitFieldInsert' : 201, + 'OpBitFieldSExtract' : 202, + 'OpBitFieldUExtract' : 203, + 'OpBitReverse' : 204, + 'OpBitCount' : 205, + 'OpDPdx' : 207, + 'OpDPdy' : 208, + 'OpFwidth' : 209, + 'OpDPdxFine' : 210, + 'OpDPdyFine' : 211, + 'OpFwidthFine' : 212, + 'OpDPdxCoarse' : 213, + 'OpDPdyCoarse' : 214, + 'OpFwidthCoarse' : 215, + 'OpEmitVertex' : 218, + 'OpEndPrimitive' : 219, + 'OpEmitStreamVertex' : 220, + 'OpEndStreamPrimitive' : 221, + 'OpControlBarrier' : 224, + 'OpMemoryBarrier' : 225, + 'OpAtomicLoad' : 227, + 'OpAtomicStore' : 228, + 'OpAtomicExchange' : 229, + 'OpAtomicCompareExchange' : 230, + 'OpAtomicCompareExchangeWeak' : 231, + 'OpAtomicIIncrement' : 232, + 'OpAtomicIDecrement' : 233, + 'OpAtomicIAdd' : 234, + 'OpAtomicISub' : 235, + 'OpAtomicSMin' : 236, + 'OpAtomicUMin' : 237, + 'OpAtomicSMax' : 238, + 'OpAtomicUMax' : 239, + 'OpAtomicAnd' : 240, + 'OpAtomicOr' : 241, + 'OpAtomicXor' : 242, + 'OpPhi' : 245, + 'OpLoopMerge' : 246, + 'OpSelectionMerge' : 247, + 'OpLabel' : 248, + 'OpBranch' : 249, + 'OpBranchConditional' : 250, + 'OpSwitch' : 251, + 'OpKill' : 252, + 'OpReturn' : 253, + 'OpReturnValue' : 254, + 'OpUnreachable' : 255, + 'OpLifetimeStart' : 256, + 'OpLifetimeStop' : 257, + 'OpGroupAsyncCopy' : 259, + 'OpGroupWaitEvents' : 260, + 'OpGroupAll' : 261, + 'OpGroupAny' : 262, + 'OpGroupBroadcast' : 263, + 'OpGroupIAdd' : 264, + 'OpGroupFAdd' : 265, + 'OpGroupFMin' : 266, + 'OpGroupUMin' : 267, + 'OpGroupSMin' : 268, + 'OpGroupFMax' : 269, + 'OpGroupUMax' : 270, + 'OpGroupSMax' : 271, + 'OpReadPipe' : 274, + 'OpWritePipe' : 275, + 'OpReservedReadPipe' : 276, + 'OpReservedWritePipe' : 277, + 'OpReserveReadPipePackets' : 278, + 'OpReserveWritePipePackets' : 279, + 'OpCommitReadPipe' : 280, + 'OpCommitWritePipe' : 281, + 'OpIsValidReserveId' : 282, + 'OpGetNumPipePackets' : 283, + 'OpGetMaxPipePackets' : 284, + 'OpGroupReserveReadPipePackets' : 285, + 'OpGroupReserveWritePipePackets' : 286, + 'OpGroupCommitReadPipe' : 287, + 'OpGroupCommitWritePipe' : 288, + 'OpEnqueueMarker' : 291, + 'OpEnqueueKernel' : 292, + 'OpGetKernelNDrangeSubGroupCount' : 293, + 'OpGetKernelNDrangeMaxSubGroupSize' : 294, + 'OpGetKernelWorkGroupSize' : 295, + 'OpGetKernelPreferredWorkGroupSizeMultiple' : 296, + 'OpRetainEvent' : 297, + 'OpReleaseEvent' : 298, + 'OpCreateUserEvent' : 299, + 'OpIsValidEvent' : 300, + 'OpSetUserEventStatus' : 301, + 'OpCaptureEventProfilingInfo' : 302, + 'OpGetDefaultQueue' : 303, + 'OpBuildNDRange' : 304, + 'OpImageSparseSampleImplicitLod' : 305, + 'OpImageSparseSampleExplicitLod' : 306, + 'OpImageSparseSampleDrefImplicitLod' : 307, + 'OpImageSparseSampleDrefExplicitLod' : 308, + 'OpImageSparseSampleProjImplicitLod' : 309, + 'OpImageSparseSampleProjExplicitLod' : 310, + 'OpImageSparseSampleProjDrefImplicitLod' : 311, + 'OpImageSparseSampleProjDrefExplicitLod' : 312, + 'OpImageSparseFetch' : 313, + 'OpImageSparseGather' : 314, + 'OpImageSparseDrefGather' : 315, + 'OpImageSparseTexelsResident' : 316, + 'OpNoLine' : 317, + 'OpAtomicFlagTestAndSet' : 318, + 'OpAtomicFlagClear' : 319, + 'OpImageSparseRead' : 320, + 'OpSizeOf' : 321, + 'OpTypePipeStorage' : 322, + 'OpConstantPipeStorage' : 323, + 'OpCreatePipeFromPipeStorage' : 324, + 'OpGetKernelLocalSizeForSubgroupCount' : 325, + 'OpGetKernelMaxNumSubgroups' : 326, + 'OpTypeNamedBarrier' : 327, + 'OpNamedBarrierInitialize' : 328, + 'OpMemoryNamedBarrier' : 329, + 'OpModuleProcessed' : 330, + 'OpSubgroupBallotKHR' : 4421, + 'OpSubgroupFirstInvocationKHR' : 4422, + 'OpSubgroupAllKHR' : 4428, + 'OpSubgroupAnyKHR' : 4429, + 'OpSubgroupAllEqualKHR' : 4430, + 'OpSubgroupReadInvocationKHR' : 4432, + 'OpGroupIAddNonUniformAMD' : 5000, + 'OpGroupFAddNonUniformAMD' : 5001, + 'OpGroupFMinNonUniformAMD' : 5002, + 'OpGroupUMinNonUniformAMD' : 5003, + 'OpGroupSMinNonUniformAMD' : 5004, + 'OpGroupFMaxNonUniformAMD' : 5005, + 'OpGroupUMaxNonUniformAMD' : 5006, + 'OpGroupSMaxNonUniformAMD' : 5007, + 'OpFragmentMaskFetchAMD' : 5011, + 'OpFragmentFetchAMD' : 5012, + 'OpSubgroupShuffleINTEL' : 5571, + 'OpSubgroupShuffleDownINTEL' : 5572, + 'OpSubgroupShuffleUpINTEL' : 5573, + 'OpSubgroupShuffleXorINTEL' : 5574, + 'OpSubgroupBlockReadINTEL' : 5575, + 'OpSubgroupBlockWriteINTEL' : 5576, + 'OpSubgroupImageBlockReadINTEL' : 5577, + 'OpSubgroupImageBlockWriteINTEL' : 5578, + }, + +} + diff --git a/ext/vulkan/vk_icd.h b/ext/vulkan/vk_icd.h index 668a4d183c..b8c7efcb6b 100644 --- a/ext/vulkan/vk_icd.h +++ b/ext/vulkan/vk_icd.h @@ -35,13 +35,19 @@ // Version 3 - Add ICD creation/destruction of KHR_surface objects. // Version 4 - Add unknown physical device extension qyering via // vk_icdGetPhysicalDeviceProcAddr. -#define CURRENT_LOADER_ICD_INTERFACE_VERSION 4 +// Version 5 - Tells ICDs that the loader is now paying attention to the +// application version of Vulkan passed into the ApplicationInfo +// structure during vkCreateInstance. This will tell the ICD +// that if the loader is older, it should automatically fail a +// call for any API version > 1.0. Otherwise, the loader will +// manually determine if it can support the expected version. +#define CURRENT_LOADER_ICD_INTERFACE_VERSION 5 #define MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION 0 #define MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION 4 typedef VkResult (VKAPI_PTR *PFN_vkNegotiateLoaderICDInterfaceVersion)(uint32_t *pVersion); // This is defined in vk_layer.h which will be found by the loader, but if an ICD is building against this -// flie directly, it won't be found. +// file directly, it won't be found. #ifndef PFN_GetPhysicalDeviceProcAddr typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName); #endif diff --git a/ext/vulkan/vk_layer.h b/ext/vulkan/vk_layer.h index 4a502a33bc..e8300c37d4 100644 --- a/ext/vulkan/vk_layer.h +++ b/ext/vulkan/vk_layer.h @@ -48,6 +48,8 @@ #define CURRENT_LOADER_LAYER_INTERFACE_VERSION 2 #define MIN_SUPPORTED_LOADER_LAYER_INTERFACE_VERSION 1 +#define VK_CURRENT_CHAIN_VERSION 1 + // Version negotiation values typedef enum VkNegotiateLayerStructType { LAYER_NEGOTIATE_UNINTIALIZED = 0, @@ -68,7 +70,7 @@ typedef struct VkNegotiateLayerInterface { typedef VkResult (VKAPI_PTR *PFN_vkNegotiateLoaderLayerInterfaceVersion)(VkNegotiateLayerInterface *pVersionStruct); // Function prototype for unknown physical device extension command -typedef VkResult(VKAPI_PTR *PFN_PhysDevExt)(VkPhysicalDevice phys_device, ...); +typedef VkResult(VKAPI_PTR *PFN_PhysDevExt)(VkPhysicalDevice phys_device); // ------------------------------------------------------------------------------------------------ // CreateInstance and CreateDevice support structures @@ -132,3 +134,62 @@ typedef struct { } u; } VkLayerDeviceCreateInfo; +#ifdef __cplusplus +extern "C" { +#endif + +VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct); + +typedef enum VkChainType { + VK_CHAIN_TYPE_UNKNOWN = 0, + VK_CHAIN_TYPE_ENUMERATE_INSTANCE_EXTENSION_PROPERTIES = 1, + VK_CHAIN_TYPE_ENUMERATE_INSTANCE_LAYER_PROPERTIES = 2, + VK_CHAIN_TYPE_ENUMERATE_INSTANCE_VERSION = 3, +} VkChainType; + +typedef struct VkChainHeader { + VkChainType type; + uint32_t version; + uint32_t size; +} VkChainHeader; + +typedef struct VkEnumerateInstanceExtensionPropertiesChain { + VkChainHeader header; + VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceExtensionPropertiesChain *, const char *, uint32_t *, + VkExtensionProperties *); + const struct VkEnumerateInstanceExtensionPropertiesChain *pNextLink; + +#if defined(__cplusplus) + inline VkResult CallDown(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) const { + return pfnNextLayer(pNextLink, pLayerName, pPropertyCount, pProperties); + } +#endif +} VkEnumerateInstanceExtensionPropertiesChain; + +typedef struct VkEnumerateInstanceLayerPropertiesChain { + VkChainHeader header; + VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceLayerPropertiesChain *, uint32_t *, VkLayerProperties *); + const struct VkEnumerateInstanceLayerPropertiesChain *pNextLink; + +#if defined(__cplusplus) + inline VkResult CallDown(uint32_t *pPropertyCount, VkLayerProperties *pProperties) const { + return pfnNextLayer(pNextLink, pPropertyCount, pProperties); + } +#endif +} VkEnumerateInstanceLayerPropertiesChain; + +typedef struct VkEnumerateInstanceVersionChain { + VkChainHeader header; + VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceVersionChain *, uint32_t *); + const struct VkEnumerateInstanceVersionChain *pNextLink; + +#if defined(__cplusplus) + inline VkResult CallDown(uint32_t *pApiVersion) const { + return pfnNextLayer(pNextLink, pApiVersion); + } +#endif +} VkEnumerateInstanceVersionChain; + +#ifdef __cplusplus +} +#endif diff --git a/ext/vulkan/vk_layer_dispatch_table.h b/ext/vulkan/vk_layer_dispatch_table.h index d6b3f11a27..572982dfd3 100644 --- a/ext/vulkan/vk_layer_dispatch_table.h +++ b/ext/vulkan/vk_layer_dispatch_table.h @@ -49,6 +49,20 @@ typedef struct VkLayerInstanceDispatchTable_ { PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties; PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties; + // ---- Core 1_1 commands + PFN_vkEnumerateInstanceVersion EnumerateInstanceVersion; + PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups; + PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2; + PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2; + PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysicalDeviceFormatProperties2; + PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysicalDeviceImageFormatProperties2; + PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysicalDeviceQueueFamilyProperties2; + PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysicalDeviceMemoryProperties2; + PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysicalDeviceSparseImageFormatProperties2; + PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties; + PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties; + PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties; + // ---- VK_KHR_surface extension commands PFN_vkDestroySurfaceKHR DestroySurfaceKHR; PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR; @@ -56,6 +70,9 @@ typedef struct VkLayerInstanceDispatchTable_ { PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR; PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR; + // ---- VK_KHR_swapchain extension commands + PFN_vkGetPhysicalDevicePresentRectanglesKHR GetPhysicalDevicePresentRectanglesKHR; + // ---- VK_KHR_display extension commands PFN_vkGetPhysicalDeviceDisplayPropertiesKHR GetPhysicalDeviceDisplayPropertiesKHR; PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayPlanePropertiesKHR; @@ -119,6 +136,22 @@ typedef struct VkLayerInstanceDispatchTable_ { PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysicalDeviceMemoryProperties2KHR; PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysicalDeviceSparseImageFormatProperties2KHR; + // ---- VK_KHR_device_group_creation extension commands + PFN_vkEnumeratePhysicalDeviceGroupsKHR EnumeratePhysicalDeviceGroupsKHR; + + // ---- VK_KHR_external_memory_capabilities extension commands + PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR GetPhysicalDeviceExternalBufferPropertiesKHR; + + // ---- VK_KHR_external_semaphore_capabilities extension commands + PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR GetPhysicalDeviceExternalSemaphorePropertiesKHR; + + // ---- VK_KHR_external_fence_capabilities extension commands + PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR GetPhysicalDeviceExternalFencePropertiesKHR; + + // ---- VK_KHR_get_surface_capabilities2 extension commands + PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR GetPhysicalDeviceSurfaceCapabilities2KHR; + PFN_vkGetPhysicalDeviceSurfaceFormats2KHR GetPhysicalDeviceSurfaceFormats2KHR; + // ---- VK_EXT_debug_report extension commands PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT; PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT; @@ -127,23 +160,11 @@ typedef struct VkLayerInstanceDispatchTable_ { // ---- VK_NV_external_memory_capabilities extension commands PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV GetPhysicalDeviceExternalImageFormatPropertiesNV; - // ---- VK_KHX_device_group extension commands - PFN_vkGetPhysicalDevicePresentRectanglesKHX GetPhysicalDevicePresentRectanglesKHX; - // ---- VK_NN_vi_surface extension commands #ifdef VK_USE_PLATFORM_VI_NN PFN_vkCreateViSurfaceNN CreateViSurfaceNN; #endif // VK_USE_PLATFORM_VI_NN - // ---- VK_KHX_device_group_creation extension commands - PFN_vkEnumeratePhysicalDeviceGroupsKHX EnumeratePhysicalDeviceGroupsKHX; - - // ---- VK_KHX_external_memory_capabilities extension commands - PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHX GetPhysicalDeviceExternalBufferPropertiesKHX; - - // ---- VK_KHX_external_semaphore_capabilities extension commands - PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHX GetPhysicalDeviceExternalSemaphorePropertiesKHX; - // ---- VK_NVX_device_generated_commands extension commands PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX GetPhysicalDeviceGeneratedCommandsPropertiesNVX; @@ -170,6 +191,14 @@ typedef struct VkLayerInstanceDispatchTable_ { #ifdef VK_USE_PLATFORM_MACOS_MVK PFN_vkCreateMacOSSurfaceMVK CreateMacOSSurfaceMVK; #endif // VK_USE_PLATFORM_MACOS_MVK + + // ---- VK_EXT_debug_utils extension commands + PFN_vkCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT; + PFN_vkDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT; + PFN_vkSubmitDebugUtilsMessageEXT SubmitDebugUtilsMessageEXT; + + // ---- VK_EXT_sample_locations extension commands + PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT GetPhysicalDeviceMultisamplePropertiesEXT; } VkLayerInstanceDispatchTable; // Device function pointer dispatch table @@ -298,27 +327,108 @@ typedef struct VkLayerDispatchTable_ { PFN_vkCmdEndRenderPass CmdEndRenderPass; PFN_vkCmdExecuteCommands CmdExecuteCommands; + // ---- Core 1_1 commands + PFN_vkBindBufferMemory2 BindBufferMemory2; + PFN_vkBindImageMemory2 BindImageMemory2; + PFN_vkGetDeviceGroupPeerMemoryFeatures GetDeviceGroupPeerMemoryFeatures; + PFN_vkCmdSetDeviceMask CmdSetDeviceMask; + PFN_vkCmdDispatchBase CmdDispatchBase; + PFN_vkGetImageMemoryRequirements2 GetImageMemoryRequirements2; + PFN_vkGetBufferMemoryRequirements2 GetBufferMemoryRequirements2; + PFN_vkGetImageSparseMemoryRequirements2 GetImageSparseMemoryRequirements2; + PFN_vkTrimCommandPool TrimCommandPool; + PFN_vkGetDeviceQueue2 GetDeviceQueue2; + PFN_vkCreateSamplerYcbcrConversion CreateSamplerYcbcrConversion; + PFN_vkDestroySamplerYcbcrConversion DestroySamplerYcbcrConversion; + PFN_vkCreateDescriptorUpdateTemplate CreateDescriptorUpdateTemplate; + PFN_vkDestroyDescriptorUpdateTemplate DestroyDescriptorUpdateTemplate; + PFN_vkUpdateDescriptorSetWithTemplate UpdateDescriptorSetWithTemplate; + PFN_vkGetDescriptorSetLayoutSupport GetDescriptorSetLayoutSupport; + // ---- VK_KHR_swapchain extension commands PFN_vkCreateSwapchainKHR CreateSwapchainKHR; PFN_vkDestroySwapchainKHR DestroySwapchainKHR; PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR; PFN_vkAcquireNextImageKHR AcquireNextImageKHR; PFN_vkQueuePresentKHR QueuePresentKHR; + PFN_vkGetDeviceGroupPresentCapabilitiesKHR GetDeviceGroupPresentCapabilitiesKHR; + PFN_vkGetDeviceGroupSurfacePresentModesKHR GetDeviceGroupSurfacePresentModesKHR; + PFN_vkAcquireNextImage2KHR AcquireNextImage2KHR; // ---- VK_KHR_display_swapchain extension commands PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR; + // ---- VK_KHR_device_group extension commands + PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR GetDeviceGroupPeerMemoryFeaturesKHR; + PFN_vkCmdSetDeviceMaskKHR CmdSetDeviceMaskKHR; + PFN_vkCmdDispatchBaseKHR CmdDispatchBaseKHR; + // ---- VK_KHR_maintenance1 extension commands PFN_vkTrimCommandPoolKHR TrimCommandPoolKHR; + // ---- VK_KHR_external_memory_win32 extension commands +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkGetMemoryWin32HandleKHR GetMemoryWin32HandleKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkGetMemoryWin32HandlePropertiesKHR GetMemoryWin32HandlePropertiesKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR + + // ---- VK_KHR_external_memory_fd extension commands + PFN_vkGetMemoryFdKHR GetMemoryFdKHR; + PFN_vkGetMemoryFdPropertiesKHR GetMemoryFdPropertiesKHR; + + // ---- VK_KHR_external_semaphore_win32 extension commands +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkImportSemaphoreWin32HandleKHR ImportSemaphoreWin32HandleKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkGetSemaphoreWin32HandleKHR GetSemaphoreWin32HandleKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR + + // ---- VK_KHR_external_semaphore_fd extension commands + PFN_vkImportSemaphoreFdKHR ImportSemaphoreFdKHR; + PFN_vkGetSemaphoreFdKHR GetSemaphoreFdKHR; + // ---- VK_KHR_push_descriptor extension commands PFN_vkCmdPushDescriptorSetKHR CmdPushDescriptorSetKHR; + PFN_vkCmdPushDescriptorSetWithTemplateKHR CmdPushDescriptorSetWithTemplateKHR; // ---- VK_KHR_descriptor_update_template extension commands PFN_vkCreateDescriptorUpdateTemplateKHR CreateDescriptorUpdateTemplateKHR; PFN_vkDestroyDescriptorUpdateTemplateKHR DestroyDescriptorUpdateTemplateKHR; PFN_vkUpdateDescriptorSetWithTemplateKHR UpdateDescriptorSetWithTemplateKHR; - PFN_vkCmdPushDescriptorSetWithTemplateKHR CmdPushDescriptorSetWithTemplateKHR; + + // ---- VK_KHR_shared_presentable_image extension commands + PFN_vkGetSwapchainStatusKHR GetSwapchainStatusKHR; + + // ---- VK_KHR_external_fence_win32 extension commands +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkImportFenceWin32HandleKHR ImportFenceWin32HandleKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkGetFenceWin32HandleKHR GetFenceWin32HandleKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR + + // ---- VK_KHR_external_fence_fd extension commands + PFN_vkImportFenceFdKHR ImportFenceFdKHR; + PFN_vkGetFenceFdKHR GetFenceFdKHR; + + // ---- VK_KHR_get_memory_requirements2 extension commands + PFN_vkGetImageMemoryRequirements2KHR GetImageMemoryRequirements2KHR; + PFN_vkGetBufferMemoryRequirements2KHR GetBufferMemoryRequirements2KHR; + PFN_vkGetImageSparseMemoryRequirements2KHR GetImageSparseMemoryRequirements2KHR; + + // ---- VK_KHR_sampler_ycbcr_conversion extension commands + PFN_vkCreateSamplerYcbcrConversionKHR CreateSamplerYcbcrConversionKHR; + PFN_vkDestroySamplerYcbcrConversionKHR DestroySamplerYcbcrConversionKHR; + + // ---- VK_KHR_bind_memory2 extension commands + PFN_vkBindBufferMemory2KHR BindBufferMemory2KHR; + PFN_vkBindImageMemory2KHR BindImageMemory2KHR; + + // ---- VK_KHR_maintenance3 extension commands + PFN_vkGetDescriptorSetLayoutSupportKHR GetDescriptorSetLayoutSupportKHR; // ---- VK_EXT_debug_marker extension commands PFN_vkDebugMarkerSetObjectTagEXT DebugMarkerSetObjectTagEXT; @@ -331,45 +441,14 @@ typedef struct VkLayerDispatchTable_ { PFN_vkCmdDrawIndirectCountAMD CmdDrawIndirectCountAMD; PFN_vkCmdDrawIndexedIndirectCountAMD CmdDrawIndexedIndirectCountAMD; + // ---- VK_AMD_shader_info extension commands + PFN_vkGetShaderInfoAMD GetShaderInfoAMD; + // ---- VK_NV_external_memory_win32 extension commands #ifdef VK_USE_PLATFORM_WIN32_KHR PFN_vkGetMemoryWin32HandleNV GetMemoryWin32HandleNV; #endif // VK_USE_PLATFORM_WIN32_KHR - // ---- VK_KHX_device_group extension commands - PFN_vkGetDeviceGroupPeerMemoryFeaturesKHX GetDeviceGroupPeerMemoryFeaturesKHX; - PFN_vkBindBufferMemory2KHX BindBufferMemory2KHX; - PFN_vkBindImageMemory2KHX BindImageMemory2KHX; - PFN_vkCmdSetDeviceMaskKHX CmdSetDeviceMaskKHX; - PFN_vkGetDeviceGroupPresentCapabilitiesKHX GetDeviceGroupPresentCapabilitiesKHX; - PFN_vkGetDeviceGroupSurfacePresentModesKHX GetDeviceGroupSurfacePresentModesKHX; - PFN_vkAcquireNextImage2KHX AcquireNextImage2KHX; - PFN_vkCmdDispatchBaseKHX CmdDispatchBaseKHX; - - // ---- VK_KHX_external_memory_win32 extension commands -#ifdef VK_USE_PLATFORM_WIN32_KHX - PFN_vkGetMemoryWin32HandleKHX GetMemoryWin32HandleKHX; -#endif // VK_USE_PLATFORM_WIN32_KHX -#ifdef VK_USE_PLATFORM_WIN32_KHX - PFN_vkGetMemoryWin32HandlePropertiesKHX GetMemoryWin32HandlePropertiesKHX; -#endif // VK_USE_PLATFORM_WIN32_KHX - - // ---- VK_KHX_external_memory_fd extension commands - PFN_vkGetMemoryFdKHX GetMemoryFdKHX; - PFN_vkGetMemoryFdPropertiesKHX GetMemoryFdPropertiesKHX; - - // ---- VK_KHX_external_semaphore_win32 extension commands -#ifdef VK_USE_PLATFORM_WIN32_KHX - PFN_vkImportSemaphoreWin32HandleKHX ImportSemaphoreWin32HandleKHX; -#endif // VK_USE_PLATFORM_WIN32_KHX -#ifdef VK_USE_PLATFORM_WIN32_KHX - PFN_vkGetSemaphoreWin32HandleKHX GetSemaphoreWin32HandleKHX; -#endif // VK_USE_PLATFORM_WIN32_KHX - - // ---- VK_KHX_external_semaphore_fd extension commands - PFN_vkImportSemaphoreFdKHX ImportSemaphoreFdKHX; - PFN_vkGetSemaphoreFdKHX GetSemaphoreFdKHX; - // ---- VK_NVX_device_generated_commands extension commands PFN_vkCmdProcessCommandsNVX CmdProcessCommandsNVX; PFN_vkCmdReserveSpaceForCommandsNVX CmdReserveSpaceForCommandsNVX; @@ -398,6 +477,31 @@ typedef struct VkLayerDispatchTable_ { // ---- VK_EXT_hdr_metadata extension commands PFN_vkSetHdrMetadataEXT SetHdrMetadataEXT; + + // ---- VK_EXT_debug_utils extension commands + PFN_vkSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT; + PFN_vkSetDebugUtilsObjectTagEXT SetDebugUtilsObjectTagEXT; + PFN_vkQueueBeginDebugUtilsLabelEXT QueueBeginDebugUtilsLabelEXT; + PFN_vkQueueEndDebugUtilsLabelEXT QueueEndDebugUtilsLabelEXT; + PFN_vkQueueInsertDebugUtilsLabelEXT QueueInsertDebugUtilsLabelEXT; + PFN_vkCmdBeginDebugUtilsLabelEXT CmdBeginDebugUtilsLabelEXT; + PFN_vkCmdEndDebugUtilsLabelEXT CmdEndDebugUtilsLabelEXT; + PFN_vkCmdInsertDebugUtilsLabelEXT CmdInsertDebugUtilsLabelEXT; + + // ---- VK_EXT_sample_locations extension commands + PFN_vkCmdSetSampleLocationsEXT CmdSetSampleLocationsEXT; + + // ---- VK_EXT_validation_cache extension commands + PFN_vkCreateValidationCacheEXT CreateValidationCacheEXT; + PFN_vkDestroyValidationCacheEXT DestroyValidationCacheEXT; + PFN_vkMergeValidationCachesEXT MergeValidationCachesEXT; + PFN_vkGetValidationCacheDataEXT GetValidationCacheDataEXT; + + // ---- VK_EXT_external_memory_host extension commands + PFN_vkGetMemoryHostPointerPropertiesEXT GetMemoryHostPointerPropertiesEXT; + + // ---- VK_AMD_buffer_marker extension commands + PFN_vkCmdWriteBufferMarkerAMD CmdWriteBufferMarkerAMD; } VkLayerDispatchTable; diff --git a/ext/vulkan/vk_platform.h b/ext/vulkan/vk_platform.h index 72f80493ca..7289299240 100644 --- a/ext/vulkan/vk_platform.h +++ b/ext/vulkan/vk_platform.h @@ -89,32 +89,4 @@ extern "C" } // extern "C" #endif // __cplusplus -// Platform-specific headers required by platform window system extensions. -// These are enabled prior to #including "vulkan.h". The same enable then -// controls inclusion of the extension interfaces in vulkan.h. - -#ifdef VK_USE_PLATFORM_ANDROID_KHR -#include -#endif - -#ifdef VK_USE_PLATFORM_MIR_KHR -#include -#endif - -#ifdef VK_USE_PLATFORM_WAYLAND_KHR -#include -#endif - -#ifdef VK_USE_PLATFORM_WIN32_KHR -#include -#endif - -#ifdef VK_USE_PLATFORM_XLIB_KHR -#include -#endif - -#ifdef VK_USE_PLATFORM_XCB_KHR -#include -#endif - #endif diff --git a/ext/vulkan/vk_sdk_platform.h b/ext/vulkan/vk_sdk_platform.h index ef9a000fb2..96d8676949 100644 --- a/ext/vulkan/vk_sdk_platform.h +++ b/ext/vulkan/vk_sdk_platform.h @@ -43,4 +43,27 @@ #endif // _WIN32 -#endif // VK_SDK_PLATFORM_H +// Check for noexcept support using clang, with fallback to Windows or GCC version numbers +#ifndef NOEXCEPT +#if defined(__clang__) +#if __has_feature(cxx_noexcept) +#define HAS_NOEXCEPT +#endif +#else +#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 +#define HAS_NOEXCEPT +#else +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026 && defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS +#define HAS_NOEXCEPT +#endif +#endif +#endif + +#ifdef HAS_NOEXCEPT +#define NOEXCEPT noexcept +#else +#define NOEXCEPT +#endif +#endif + +#endif // VK_SDK_PLATFORM_H diff --git a/ext/vulkan/vulkan.h b/ext/vulkan/vulkan.h index b19c1efff9..d05c8490a5 100644 --- a/ext/vulkan/vulkan.h +++ b/ext/vulkan/vulkan.h @@ -1,12 +1,8 @@ #ifndef VULKAN_H_ #define VULKAN_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* -** Copyright (c) 2015-2017 The Khronos Group Inc. +** Copyright (c) 2015-2018 The Khronos Group Inc. ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -21,6840 +17,63 @@ extern "C" { ** limitations under the License. */ -/* -** This header is generated from the Khronos Vulkan XML API Registry. -** -*/ - - -#define VK_VERSION_1_0 1 #include "vk_platform.h" - -#define VK_MAKE_VERSION(major, minor, patch) \ - (((major) << 22) | ((minor) << 12) | (patch)) - -// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. -//#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 - -// Vulkan 1.0 version number -#define VK_API_VERSION_1_0 VK_MAKE_VERSION(1, 0, 0)// Patch version should always be set to 0 - -#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) -#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) -#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) -// Version of this file -#define VK_HEADER_VERSION 61 - - -#define VK_NULL_HANDLE 0 - - - -#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; - - -#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE) -#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) - #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object; -#else - #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object; -#endif -#endif - - - -typedef uint32_t VkFlags; -typedef uint32_t VkBool32; -typedef uint64_t VkDeviceSize; -typedef uint32_t VkSampleMask; - -VK_DEFINE_HANDLE(VkInstance) -VK_DEFINE_HANDLE(VkPhysicalDevice) -VK_DEFINE_HANDLE(VkDevice) -VK_DEFINE_HANDLE(VkQueue) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore) -VK_DEFINE_HANDLE(VkCommandBuffer) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipeline) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) - -#define VK_LOD_CLAMP_NONE 1000.0f -#define VK_REMAINING_MIP_LEVELS (~0U) -#define VK_REMAINING_ARRAY_LAYERS (~0U) -#define VK_WHOLE_SIZE (~0ULL) -#define VK_ATTACHMENT_UNUSED (~0U) -#define VK_TRUE 1 -#define VK_FALSE 0 -#define VK_QUEUE_FAMILY_IGNORED (~0U) -#define VK_SUBPASS_EXTERNAL (~0U) -#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256 -#define VK_UUID_SIZE 16 -#define VK_MAX_MEMORY_TYPES 32 -#define VK_MAX_MEMORY_HEAPS 16 -#define VK_MAX_EXTENSION_NAME_SIZE 256 -#define VK_MAX_DESCRIPTION_SIZE 256 - - -typedef enum VkPipelineCacheHeaderVersion { - VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, - VK_PIPELINE_CACHE_HEADER_VERSION_BEGIN_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE, - VK_PIPELINE_CACHE_HEADER_VERSION_END_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE, - VK_PIPELINE_CACHE_HEADER_VERSION_RANGE_SIZE = (VK_PIPELINE_CACHE_HEADER_VERSION_ONE - VK_PIPELINE_CACHE_HEADER_VERSION_ONE + 1), - VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF -} VkPipelineCacheHeaderVersion; - -typedef enum VkResult { - VK_SUCCESS = 0, - VK_NOT_READY = 1, - VK_TIMEOUT = 2, - VK_EVENT_SET = 3, - VK_EVENT_RESET = 4, - VK_INCOMPLETE = 5, - VK_ERROR_OUT_OF_HOST_MEMORY = -1, - VK_ERROR_OUT_OF_DEVICE_MEMORY = -2, - VK_ERROR_INITIALIZATION_FAILED = -3, - VK_ERROR_DEVICE_LOST = -4, - VK_ERROR_MEMORY_MAP_FAILED = -5, - VK_ERROR_LAYER_NOT_PRESENT = -6, - VK_ERROR_EXTENSION_NOT_PRESENT = -7, - VK_ERROR_FEATURE_NOT_PRESENT = -8, - VK_ERROR_INCOMPATIBLE_DRIVER = -9, - VK_ERROR_TOO_MANY_OBJECTS = -10, - VK_ERROR_FORMAT_NOT_SUPPORTED = -11, - VK_ERROR_FRAGMENTED_POOL = -12, - VK_ERROR_SURFACE_LOST_KHR = -1000000000, - VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001, - VK_SUBOPTIMAL_KHR = 1000001003, - VK_ERROR_OUT_OF_DATE_KHR = -1000001004, - VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, - VK_ERROR_VALIDATION_FAILED_EXT = -1000011001, - VK_ERROR_INVALID_SHADER_NV = -1000012000, - VK_ERROR_OUT_OF_POOL_MEMORY_KHR = -1000069000, - VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = -1000072003, - VK_RESULT_BEGIN_RANGE = VK_ERROR_FRAGMENTED_POOL, - VK_RESULT_END_RANGE = VK_INCOMPLETE, - VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FRAGMENTED_POOL + 1), - VK_RESULT_MAX_ENUM = 0x7FFFFFFF -} VkResult; - -typedef enum VkStructureType { - VK_STRUCTURE_TYPE_APPLICATION_INFO = 0, - VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1, - VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO = 2, - VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO = 3, - VK_STRUCTURE_TYPE_SUBMIT_INFO = 4, - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO = 5, - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE = 6, - VK_STRUCTURE_TYPE_BIND_SPARSE_INFO = 7, - VK_STRUCTURE_TYPE_FENCE_CREATE_INFO = 8, - VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO = 9, - VK_STRUCTURE_TYPE_EVENT_CREATE_INFO = 10, - VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO = 11, - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO = 12, - VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO = 13, - VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO = 14, - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO = 15, - VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO = 16, - VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO = 17, - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO = 18, - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 19, - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20, - VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO = 21, - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO = 22, - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO = 23, - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO = 24, - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO = 25, - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO = 26, - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO = 27, - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO = 28, - VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO = 29, - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO = 30, - VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO = 31, - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO = 32, - VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO = 33, - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO = 34, - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET = 35, - VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET = 36, - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO = 37, - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO = 38, - VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO = 39, - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO = 40, - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO = 41, - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO = 42, - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO = 43, - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER = 44, - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER = 45, - VK_STRUCTURE_TYPE_MEMORY_BARRIER = 46, - VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47, - VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48, - VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000, - VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001, - VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR = 1000002000, - VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001, - VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR = 1000003000, - VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000, - VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000, - VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000, - VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000, - VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000, - VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, - VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000, - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD = 1000018000, - VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000, - VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001, - VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT = 1000022002, - VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000, - VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001, - VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002, - VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000, - VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHX = 1000053000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHX = 1000053001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHX = 1000053002, - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000, - VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001, - VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000, - VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001, - VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = 1000059000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = 1000059001, - VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = 1000059002, - VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059003, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = 1000059004, - VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = 1000059005, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = 1000059006, - VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059007, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008, - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHX = 1000060000, - VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHX = 1000060003, - VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHX = 1000060004, - VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHX = 1000060005, - VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHX = 1000060006, - VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHX = 1000060010, - VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHX = 1000060013, - VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHX = 1000060014, - VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHX = 1000060007, - VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHX = 1000060008, - VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHX = 1000060009, - VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHX = 1000060011, - VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHX = 1000060012, - VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000, - VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX = 1000070000, - VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX = 1000070001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = 1000071000, - VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR = 1000071001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR = 1000071002, - VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR = 1000071003, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR = 1000071004, - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR = 1000072000, - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR = 1000072001, - VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR = 1000072002, - VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000, - VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001, - VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002, - VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR = 1000073003, - VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR = 1000074000, - VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR = 1000074001, - VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR = 1000074002, - VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR = 1000075000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = 1000076000, - VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR = 1000076001, - VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = 1000077000, - VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078000, - VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078001, - VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR = 1000078002, - VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR = 1000078003, - VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR = 1000079000, - VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR = 1000079001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = 1000083000, - VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000, - VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000, - VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000, - VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001, - VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002, - VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003, - VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004, - VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005, - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000, - VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT = 1000090000, - VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000, - VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT = 1000091001, - VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT = 1000091002, - VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT = 1000091003, - VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX = 1000097000, - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV = 1000098000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT = 1000099000, - VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001, - VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000, - VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = 1000112000, - VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = 1000112001, - VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = 1000113000, - VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000, - VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001, - VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR = 1000114002, - VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR = 1000115000, - VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR = 1000115001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR = 1000117000, - VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = 1000117001, - VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR = 1000117002, - VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = 1000117003, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000, - VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001, - VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = 1000120000, - VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000, - VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000, - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = 1000127000, - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = 1000127001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000, - VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001, - VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000, - VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001, - VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT = 1000143003, - VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT = 1000143004, - VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146000, - VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146001, - VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146002, - VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = 1000146003, - VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = 1000146004, - VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR = 1000147000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT = 1000148000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001, - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002, - VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000, - VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000, - VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR = 1000156000, - VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR = 1000156001, - VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR = 1000156002, - VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR = 1000156003, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR = 1000156004, - VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR = 1000156005, - VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR = 1000157000, - VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR = 1000157001, - VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000, - VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001, - VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO, - VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO, - VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1), - VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkStructureType; - -typedef enum VkSystemAllocationScope { - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0, - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1, - VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2, - VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3, - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4, - VK_SYSTEM_ALLOCATION_SCOPE_BEGIN_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_COMMAND, - VK_SYSTEM_ALLOCATION_SCOPE_END_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE, - VK_SYSTEM_ALLOCATION_SCOPE_RANGE_SIZE = (VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND + 1), - VK_SYSTEM_ALLOCATION_SCOPE_MAX_ENUM = 0x7FFFFFFF -} VkSystemAllocationScope; - -typedef enum VkInternalAllocationType { - VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0, - VK_INTERNAL_ALLOCATION_TYPE_BEGIN_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE, - VK_INTERNAL_ALLOCATION_TYPE_END_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE, - VK_INTERNAL_ALLOCATION_TYPE_RANGE_SIZE = (VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE - VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE + 1), - VK_INTERNAL_ALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkInternalAllocationType; - -typedef enum VkFormat { - VK_FORMAT_UNDEFINED = 0, - VK_FORMAT_R4G4_UNORM_PACK8 = 1, - VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2, - VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3, - VK_FORMAT_R5G6B5_UNORM_PACK16 = 4, - VK_FORMAT_B5G6R5_UNORM_PACK16 = 5, - VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6, - VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7, - VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8, - VK_FORMAT_R8_UNORM = 9, - VK_FORMAT_R8_SNORM = 10, - VK_FORMAT_R8_USCALED = 11, - VK_FORMAT_R8_SSCALED = 12, - VK_FORMAT_R8_UINT = 13, - VK_FORMAT_R8_SINT = 14, - VK_FORMAT_R8_SRGB = 15, - VK_FORMAT_R8G8_UNORM = 16, - VK_FORMAT_R8G8_SNORM = 17, - VK_FORMAT_R8G8_USCALED = 18, - VK_FORMAT_R8G8_SSCALED = 19, - VK_FORMAT_R8G8_UINT = 20, - VK_FORMAT_R8G8_SINT = 21, - VK_FORMAT_R8G8_SRGB = 22, - VK_FORMAT_R8G8B8_UNORM = 23, - VK_FORMAT_R8G8B8_SNORM = 24, - VK_FORMAT_R8G8B8_USCALED = 25, - VK_FORMAT_R8G8B8_SSCALED = 26, - VK_FORMAT_R8G8B8_UINT = 27, - VK_FORMAT_R8G8B8_SINT = 28, - VK_FORMAT_R8G8B8_SRGB = 29, - VK_FORMAT_B8G8R8_UNORM = 30, - VK_FORMAT_B8G8R8_SNORM = 31, - VK_FORMAT_B8G8R8_USCALED = 32, - VK_FORMAT_B8G8R8_SSCALED = 33, - VK_FORMAT_B8G8R8_UINT = 34, - VK_FORMAT_B8G8R8_SINT = 35, - VK_FORMAT_B8G8R8_SRGB = 36, - VK_FORMAT_R8G8B8A8_UNORM = 37, - VK_FORMAT_R8G8B8A8_SNORM = 38, - VK_FORMAT_R8G8B8A8_USCALED = 39, - VK_FORMAT_R8G8B8A8_SSCALED = 40, - VK_FORMAT_R8G8B8A8_UINT = 41, - VK_FORMAT_R8G8B8A8_SINT = 42, - VK_FORMAT_R8G8B8A8_SRGB = 43, - VK_FORMAT_B8G8R8A8_UNORM = 44, - VK_FORMAT_B8G8R8A8_SNORM = 45, - VK_FORMAT_B8G8R8A8_USCALED = 46, - VK_FORMAT_B8G8R8A8_SSCALED = 47, - VK_FORMAT_B8G8R8A8_UINT = 48, - VK_FORMAT_B8G8R8A8_SINT = 49, - VK_FORMAT_B8G8R8A8_SRGB = 50, - VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51, - VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52, - VK_FORMAT_A8B8G8R8_USCALED_PACK32 = 53, - VK_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54, - VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55, - VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56, - VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57, - VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58, - VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59, - VK_FORMAT_A2R10G10B10_USCALED_PACK32 = 60, - VK_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61, - VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62, - VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63, - VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64, - VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65, - VK_FORMAT_A2B10G10R10_USCALED_PACK32 = 66, - VK_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67, - VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68, - VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69, - VK_FORMAT_R16_UNORM = 70, - VK_FORMAT_R16_SNORM = 71, - VK_FORMAT_R16_USCALED = 72, - VK_FORMAT_R16_SSCALED = 73, - VK_FORMAT_R16_UINT = 74, - VK_FORMAT_R16_SINT = 75, - VK_FORMAT_R16_SFLOAT = 76, - VK_FORMAT_R16G16_UNORM = 77, - VK_FORMAT_R16G16_SNORM = 78, - VK_FORMAT_R16G16_USCALED = 79, - VK_FORMAT_R16G16_SSCALED = 80, - VK_FORMAT_R16G16_UINT = 81, - VK_FORMAT_R16G16_SINT = 82, - VK_FORMAT_R16G16_SFLOAT = 83, - VK_FORMAT_R16G16B16_UNORM = 84, - VK_FORMAT_R16G16B16_SNORM = 85, - VK_FORMAT_R16G16B16_USCALED = 86, - VK_FORMAT_R16G16B16_SSCALED = 87, - VK_FORMAT_R16G16B16_UINT = 88, - VK_FORMAT_R16G16B16_SINT = 89, - VK_FORMAT_R16G16B16_SFLOAT = 90, - VK_FORMAT_R16G16B16A16_UNORM = 91, - VK_FORMAT_R16G16B16A16_SNORM = 92, - VK_FORMAT_R16G16B16A16_USCALED = 93, - VK_FORMAT_R16G16B16A16_SSCALED = 94, - VK_FORMAT_R16G16B16A16_UINT = 95, - VK_FORMAT_R16G16B16A16_SINT = 96, - VK_FORMAT_R16G16B16A16_SFLOAT = 97, - VK_FORMAT_R32_UINT = 98, - VK_FORMAT_R32_SINT = 99, - VK_FORMAT_R32_SFLOAT = 100, - VK_FORMAT_R32G32_UINT = 101, - VK_FORMAT_R32G32_SINT = 102, - VK_FORMAT_R32G32_SFLOAT = 103, - VK_FORMAT_R32G32B32_UINT = 104, - VK_FORMAT_R32G32B32_SINT = 105, - VK_FORMAT_R32G32B32_SFLOAT = 106, - VK_FORMAT_R32G32B32A32_UINT = 107, - VK_FORMAT_R32G32B32A32_SINT = 108, - VK_FORMAT_R32G32B32A32_SFLOAT = 109, - VK_FORMAT_R64_UINT = 110, - VK_FORMAT_R64_SINT = 111, - VK_FORMAT_R64_SFLOAT = 112, - VK_FORMAT_R64G64_UINT = 113, - VK_FORMAT_R64G64_SINT = 114, - VK_FORMAT_R64G64_SFLOAT = 115, - VK_FORMAT_R64G64B64_UINT = 116, - VK_FORMAT_R64G64B64_SINT = 117, - VK_FORMAT_R64G64B64_SFLOAT = 118, - VK_FORMAT_R64G64B64A64_UINT = 119, - VK_FORMAT_R64G64B64A64_SINT = 120, - VK_FORMAT_R64G64B64A64_SFLOAT = 121, - VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122, - VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123, - VK_FORMAT_D16_UNORM = 124, - VK_FORMAT_X8_D24_UNORM_PACK32 = 125, - VK_FORMAT_D32_SFLOAT = 126, - VK_FORMAT_S8_UINT = 127, - VK_FORMAT_D16_UNORM_S8_UINT = 128, - VK_FORMAT_D24_UNORM_S8_UINT = 129, - VK_FORMAT_D32_SFLOAT_S8_UINT = 130, - VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131, - VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132, - VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133, - VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134, - VK_FORMAT_BC2_UNORM_BLOCK = 135, - VK_FORMAT_BC2_SRGB_BLOCK = 136, - VK_FORMAT_BC3_UNORM_BLOCK = 137, - VK_FORMAT_BC3_SRGB_BLOCK = 138, - VK_FORMAT_BC4_UNORM_BLOCK = 139, - VK_FORMAT_BC4_SNORM_BLOCK = 140, - VK_FORMAT_BC5_UNORM_BLOCK = 141, - VK_FORMAT_BC5_SNORM_BLOCK = 142, - VK_FORMAT_BC6H_UFLOAT_BLOCK = 143, - VK_FORMAT_BC6H_SFLOAT_BLOCK = 144, - VK_FORMAT_BC7_UNORM_BLOCK = 145, - VK_FORMAT_BC7_SRGB_BLOCK = 146, - VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147, - VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148, - VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149, - VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150, - VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151, - VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152, - VK_FORMAT_EAC_R11_UNORM_BLOCK = 153, - VK_FORMAT_EAC_R11_SNORM_BLOCK = 154, - VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155, - VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156, - VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157, - VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158, - VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159, - VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160, - VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161, - VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162, - VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163, - VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164, - VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165, - VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166, - VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167, - VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168, - VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169, - VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170, - VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171, - VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172, - VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173, - VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174, - VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175, - VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176, - VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177, - VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178, - VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179, - VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180, - VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181, - VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182, - VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183, - VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184, - VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000, - VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001, - VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002, - VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003, - VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004, - VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005, - VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006, - VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007, - VK_FORMAT_G8B8G8R8_422_UNORM_KHR = 1000156000, - VK_FORMAT_B8G8R8G8_422_UNORM_KHR = 1000156001, - VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR = 1000156002, - VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR = 1000156003, - VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR = 1000156004, - VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR = 1000156005, - VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR = 1000156006, - VK_FORMAT_R10X6_UNORM_PACK16_KHR = 1000156007, - VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR = 1000156008, - VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR = 1000156009, - VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR = 1000156010, - VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR = 1000156011, - VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR = 1000156012, - VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR = 1000156013, - VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR = 1000156014, - VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR = 1000156015, - VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR = 1000156016, - VK_FORMAT_R12X4_UNORM_PACK16_KHR = 1000156017, - VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR = 1000156018, - VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR = 1000156019, - VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR = 1000156020, - VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR = 1000156021, - VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR = 1000156022, - VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR = 1000156023, - VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR = 1000156024, - VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR = 1000156025, - VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR = 1000156026, - VK_FORMAT_G16B16G16R16_422_UNORM_KHR = 1000156027, - VK_FORMAT_B16G16R16G16_422_UNORM_KHR = 1000156028, - VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR = 1000156029, - VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR = 1000156030, - VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR = 1000156031, - VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR = 1000156032, - VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR = 1000156033, - VK_FORMAT_BEGIN_RANGE = VK_FORMAT_UNDEFINED, - VK_FORMAT_END_RANGE = VK_FORMAT_ASTC_12x12_SRGB_BLOCK, - VK_FORMAT_RANGE_SIZE = (VK_FORMAT_ASTC_12x12_SRGB_BLOCK - VK_FORMAT_UNDEFINED + 1), - VK_FORMAT_MAX_ENUM = 0x7FFFFFFF -} VkFormat; - -typedef enum VkImageType { - VK_IMAGE_TYPE_1D = 0, - VK_IMAGE_TYPE_2D = 1, - VK_IMAGE_TYPE_3D = 2, - VK_IMAGE_TYPE_BEGIN_RANGE = VK_IMAGE_TYPE_1D, - VK_IMAGE_TYPE_END_RANGE = VK_IMAGE_TYPE_3D, - VK_IMAGE_TYPE_RANGE_SIZE = (VK_IMAGE_TYPE_3D - VK_IMAGE_TYPE_1D + 1), - VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkImageType; - -typedef enum VkImageTiling { - VK_IMAGE_TILING_OPTIMAL = 0, - VK_IMAGE_TILING_LINEAR = 1, - VK_IMAGE_TILING_BEGIN_RANGE = VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_TILING_END_RANGE = VK_IMAGE_TILING_LINEAR, - VK_IMAGE_TILING_RANGE_SIZE = (VK_IMAGE_TILING_LINEAR - VK_IMAGE_TILING_OPTIMAL + 1), - VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF -} VkImageTiling; - -typedef enum VkPhysicalDeviceType { - VK_PHYSICAL_DEVICE_TYPE_OTHER = 0, - VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1, - VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2, - VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3, - VK_PHYSICAL_DEVICE_TYPE_CPU = 4, - VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE = VK_PHYSICAL_DEVICE_TYPE_OTHER, - VK_PHYSICAL_DEVICE_TYPE_END_RANGE = VK_PHYSICAL_DEVICE_TYPE_CPU, - VK_PHYSICAL_DEVICE_TYPE_RANGE_SIZE = (VK_PHYSICAL_DEVICE_TYPE_CPU - VK_PHYSICAL_DEVICE_TYPE_OTHER + 1), - VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkPhysicalDeviceType; - -typedef enum VkQueryType { - VK_QUERY_TYPE_OCCLUSION = 0, - VK_QUERY_TYPE_PIPELINE_STATISTICS = 1, - VK_QUERY_TYPE_TIMESTAMP = 2, - VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION, - VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_TIMESTAMP, - VK_QUERY_TYPE_RANGE_SIZE = (VK_QUERY_TYPE_TIMESTAMP - VK_QUERY_TYPE_OCCLUSION + 1), - VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkQueryType; - -typedef enum VkSharingMode { - VK_SHARING_MODE_EXCLUSIVE = 0, - VK_SHARING_MODE_CONCURRENT = 1, - VK_SHARING_MODE_BEGIN_RANGE = VK_SHARING_MODE_EXCLUSIVE, - VK_SHARING_MODE_END_RANGE = VK_SHARING_MODE_CONCURRENT, - VK_SHARING_MODE_RANGE_SIZE = (VK_SHARING_MODE_CONCURRENT - VK_SHARING_MODE_EXCLUSIVE + 1), - VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF -} VkSharingMode; - -typedef enum VkImageLayout { - VK_IMAGE_LAYOUT_UNDEFINED = 0, - VK_IMAGE_LAYOUT_GENERAL = 1, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7, - VK_IMAGE_LAYOUT_PREINITIALIZED = 8, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, - VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = 1000117000, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = 1000117001, - VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_END_RANGE = VK_IMAGE_LAYOUT_PREINITIALIZED, - VK_IMAGE_LAYOUT_RANGE_SIZE = (VK_IMAGE_LAYOUT_PREINITIALIZED - VK_IMAGE_LAYOUT_UNDEFINED + 1), - VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF -} VkImageLayout; - -typedef enum VkImageViewType { - VK_IMAGE_VIEW_TYPE_1D = 0, - VK_IMAGE_VIEW_TYPE_2D = 1, - VK_IMAGE_VIEW_TYPE_3D = 2, - VK_IMAGE_VIEW_TYPE_CUBE = 3, - VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4, - VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5, - VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6, - VK_IMAGE_VIEW_TYPE_BEGIN_RANGE = VK_IMAGE_VIEW_TYPE_1D, - VK_IMAGE_VIEW_TYPE_END_RANGE = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, - VK_IMAGE_VIEW_TYPE_RANGE_SIZE = (VK_IMAGE_VIEW_TYPE_CUBE_ARRAY - VK_IMAGE_VIEW_TYPE_1D + 1), - VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkImageViewType; - -typedef enum VkComponentSwizzle { - VK_COMPONENT_SWIZZLE_IDENTITY = 0, - VK_COMPONENT_SWIZZLE_ZERO = 1, - VK_COMPONENT_SWIZZLE_ONE = 2, - VK_COMPONENT_SWIZZLE_R = 3, - VK_COMPONENT_SWIZZLE_G = 4, - VK_COMPONENT_SWIZZLE_B = 5, - VK_COMPONENT_SWIZZLE_A = 6, - VK_COMPONENT_SWIZZLE_BEGIN_RANGE = VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_END_RANGE = VK_COMPONENT_SWIZZLE_A, - VK_COMPONENT_SWIZZLE_RANGE_SIZE = (VK_COMPONENT_SWIZZLE_A - VK_COMPONENT_SWIZZLE_IDENTITY + 1), - VK_COMPONENT_SWIZZLE_MAX_ENUM = 0x7FFFFFFF -} VkComponentSwizzle; - -typedef enum VkVertexInputRate { - VK_VERTEX_INPUT_RATE_VERTEX = 0, - VK_VERTEX_INPUT_RATE_INSTANCE = 1, - VK_VERTEX_INPUT_RATE_BEGIN_RANGE = VK_VERTEX_INPUT_RATE_VERTEX, - VK_VERTEX_INPUT_RATE_END_RANGE = VK_VERTEX_INPUT_RATE_INSTANCE, - VK_VERTEX_INPUT_RATE_RANGE_SIZE = (VK_VERTEX_INPUT_RATE_INSTANCE - VK_VERTEX_INPUT_RATE_VERTEX + 1), - VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF -} VkVertexInputRate; - -typedef enum VkPrimitiveTopology { - VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0, - VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1, - VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5, - VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6, - VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9, - VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10, - VK_PRIMITIVE_TOPOLOGY_BEGIN_RANGE = VK_PRIMITIVE_TOPOLOGY_POINT_LIST, - VK_PRIMITIVE_TOPOLOGY_END_RANGE = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, - VK_PRIMITIVE_TOPOLOGY_RANGE_SIZE = (VK_PRIMITIVE_TOPOLOGY_PATCH_LIST - VK_PRIMITIVE_TOPOLOGY_POINT_LIST + 1), - VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF -} VkPrimitiveTopology; - -typedef enum VkPolygonMode { - VK_POLYGON_MODE_FILL = 0, - VK_POLYGON_MODE_LINE = 1, - VK_POLYGON_MODE_POINT = 2, - VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000, - VK_POLYGON_MODE_BEGIN_RANGE = VK_POLYGON_MODE_FILL, - VK_POLYGON_MODE_END_RANGE = VK_POLYGON_MODE_POINT, - VK_POLYGON_MODE_RANGE_SIZE = (VK_POLYGON_MODE_POINT - VK_POLYGON_MODE_FILL + 1), - VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF -} VkPolygonMode; - -typedef enum VkFrontFace { - VK_FRONT_FACE_COUNTER_CLOCKWISE = 0, - VK_FRONT_FACE_CLOCKWISE = 1, - VK_FRONT_FACE_BEGIN_RANGE = VK_FRONT_FACE_COUNTER_CLOCKWISE, - VK_FRONT_FACE_END_RANGE = VK_FRONT_FACE_CLOCKWISE, - VK_FRONT_FACE_RANGE_SIZE = (VK_FRONT_FACE_CLOCKWISE - VK_FRONT_FACE_COUNTER_CLOCKWISE + 1), - VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF -} VkFrontFace; - -typedef enum VkCompareOp { - VK_COMPARE_OP_NEVER = 0, - VK_COMPARE_OP_LESS = 1, - VK_COMPARE_OP_EQUAL = 2, - VK_COMPARE_OP_LESS_OR_EQUAL = 3, - VK_COMPARE_OP_GREATER = 4, - VK_COMPARE_OP_NOT_EQUAL = 5, - VK_COMPARE_OP_GREATER_OR_EQUAL = 6, - VK_COMPARE_OP_ALWAYS = 7, - VK_COMPARE_OP_BEGIN_RANGE = VK_COMPARE_OP_NEVER, - VK_COMPARE_OP_END_RANGE = VK_COMPARE_OP_ALWAYS, - VK_COMPARE_OP_RANGE_SIZE = (VK_COMPARE_OP_ALWAYS - VK_COMPARE_OP_NEVER + 1), - VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF -} VkCompareOp; - -typedef enum VkStencilOp { - VK_STENCIL_OP_KEEP = 0, - VK_STENCIL_OP_ZERO = 1, - VK_STENCIL_OP_REPLACE = 2, - VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3, - VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4, - VK_STENCIL_OP_INVERT = 5, - VK_STENCIL_OP_INCREMENT_AND_WRAP = 6, - VK_STENCIL_OP_DECREMENT_AND_WRAP = 7, - VK_STENCIL_OP_BEGIN_RANGE = VK_STENCIL_OP_KEEP, - VK_STENCIL_OP_END_RANGE = VK_STENCIL_OP_DECREMENT_AND_WRAP, - VK_STENCIL_OP_RANGE_SIZE = (VK_STENCIL_OP_DECREMENT_AND_WRAP - VK_STENCIL_OP_KEEP + 1), - VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF -} VkStencilOp; - -typedef enum VkLogicOp { - VK_LOGIC_OP_CLEAR = 0, - VK_LOGIC_OP_AND = 1, - VK_LOGIC_OP_AND_REVERSE = 2, - VK_LOGIC_OP_COPY = 3, - VK_LOGIC_OP_AND_INVERTED = 4, - VK_LOGIC_OP_NO_OP = 5, - VK_LOGIC_OP_XOR = 6, - VK_LOGIC_OP_OR = 7, - VK_LOGIC_OP_NOR = 8, - VK_LOGIC_OP_EQUIVALENT = 9, - VK_LOGIC_OP_INVERT = 10, - VK_LOGIC_OP_OR_REVERSE = 11, - VK_LOGIC_OP_COPY_INVERTED = 12, - VK_LOGIC_OP_OR_INVERTED = 13, - VK_LOGIC_OP_NAND = 14, - VK_LOGIC_OP_SET = 15, - VK_LOGIC_OP_BEGIN_RANGE = VK_LOGIC_OP_CLEAR, - VK_LOGIC_OP_END_RANGE = VK_LOGIC_OP_SET, - VK_LOGIC_OP_RANGE_SIZE = (VK_LOGIC_OP_SET - VK_LOGIC_OP_CLEAR + 1), - VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF -} VkLogicOp; - -typedef enum VkBlendFactor { - VK_BLEND_FACTOR_ZERO = 0, - VK_BLEND_FACTOR_ONE = 1, - VK_BLEND_FACTOR_SRC_COLOR = 2, - VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = 3, - VK_BLEND_FACTOR_DST_COLOR = 4, - VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR = 5, - VK_BLEND_FACTOR_SRC_ALPHA = 6, - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = 7, - VK_BLEND_FACTOR_DST_ALPHA = 8, - VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = 9, - VK_BLEND_FACTOR_CONSTANT_COLOR = 10, - VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR = 11, - VK_BLEND_FACTOR_CONSTANT_ALPHA = 12, - VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = 13, - VK_BLEND_FACTOR_SRC_ALPHA_SATURATE = 14, - VK_BLEND_FACTOR_SRC1_COLOR = 15, - VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16, - VK_BLEND_FACTOR_SRC1_ALPHA = 17, - VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18, - VK_BLEND_FACTOR_BEGIN_RANGE = VK_BLEND_FACTOR_ZERO, - VK_BLEND_FACTOR_END_RANGE = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, - VK_BLEND_FACTOR_RANGE_SIZE = (VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA - VK_BLEND_FACTOR_ZERO + 1), - VK_BLEND_FACTOR_MAX_ENUM = 0x7FFFFFFF -} VkBlendFactor; - -typedef enum VkBlendOp { - VK_BLEND_OP_ADD = 0, - VK_BLEND_OP_SUBTRACT = 1, - VK_BLEND_OP_REVERSE_SUBTRACT = 2, - VK_BLEND_OP_MIN = 3, - VK_BLEND_OP_MAX = 4, - VK_BLEND_OP_ZERO_EXT = 1000148000, - VK_BLEND_OP_SRC_EXT = 1000148001, - VK_BLEND_OP_DST_EXT = 1000148002, - VK_BLEND_OP_SRC_OVER_EXT = 1000148003, - VK_BLEND_OP_DST_OVER_EXT = 1000148004, - VK_BLEND_OP_SRC_IN_EXT = 1000148005, - VK_BLEND_OP_DST_IN_EXT = 1000148006, - VK_BLEND_OP_SRC_OUT_EXT = 1000148007, - VK_BLEND_OP_DST_OUT_EXT = 1000148008, - VK_BLEND_OP_SRC_ATOP_EXT = 1000148009, - VK_BLEND_OP_DST_ATOP_EXT = 1000148010, - VK_BLEND_OP_XOR_EXT = 1000148011, - VK_BLEND_OP_MULTIPLY_EXT = 1000148012, - VK_BLEND_OP_SCREEN_EXT = 1000148013, - VK_BLEND_OP_OVERLAY_EXT = 1000148014, - VK_BLEND_OP_DARKEN_EXT = 1000148015, - VK_BLEND_OP_LIGHTEN_EXT = 1000148016, - VK_BLEND_OP_COLORDODGE_EXT = 1000148017, - VK_BLEND_OP_COLORBURN_EXT = 1000148018, - VK_BLEND_OP_HARDLIGHT_EXT = 1000148019, - VK_BLEND_OP_SOFTLIGHT_EXT = 1000148020, - VK_BLEND_OP_DIFFERENCE_EXT = 1000148021, - VK_BLEND_OP_EXCLUSION_EXT = 1000148022, - VK_BLEND_OP_INVERT_EXT = 1000148023, - VK_BLEND_OP_INVERT_RGB_EXT = 1000148024, - VK_BLEND_OP_LINEARDODGE_EXT = 1000148025, - VK_BLEND_OP_LINEARBURN_EXT = 1000148026, - VK_BLEND_OP_VIVIDLIGHT_EXT = 1000148027, - VK_BLEND_OP_LINEARLIGHT_EXT = 1000148028, - VK_BLEND_OP_PINLIGHT_EXT = 1000148029, - VK_BLEND_OP_HARDMIX_EXT = 1000148030, - VK_BLEND_OP_HSL_HUE_EXT = 1000148031, - VK_BLEND_OP_HSL_SATURATION_EXT = 1000148032, - VK_BLEND_OP_HSL_COLOR_EXT = 1000148033, - VK_BLEND_OP_HSL_LUMINOSITY_EXT = 1000148034, - VK_BLEND_OP_PLUS_EXT = 1000148035, - VK_BLEND_OP_PLUS_CLAMPED_EXT = 1000148036, - VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT = 1000148037, - VK_BLEND_OP_PLUS_DARKER_EXT = 1000148038, - VK_BLEND_OP_MINUS_EXT = 1000148039, - VK_BLEND_OP_MINUS_CLAMPED_EXT = 1000148040, - VK_BLEND_OP_CONTRAST_EXT = 1000148041, - VK_BLEND_OP_INVERT_OVG_EXT = 1000148042, - VK_BLEND_OP_RED_EXT = 1000148043, - VK_BLEND_OP_GREEN_EXT = 1000148044, - VK_BLEND_OP_BLUE_EXT = 1000148045, - VK_BLEND_OP_BEGIN_RANGE = VK_BLEND_OP_ADD, - VK_BLEND_OP_END_RANGE = VK_BLEND_OP_MAX, - VK_BLEND_OP_RANGE_SIZE = (VK_BLEND_OP_MAX - VK_BLEND_OP_ADD + 1), - VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF -} VkBlendOp; - -typedef enum VkDynamicState { - VK_DYNAMIC_STATE_VIEWPORT = 0, - VK_DYNAMIC_STATE_SCISSOR = 1, - VK_DYNAMIC_STATE_LINE_WIDTH = 2, - VK_DYNAMIC_STATE_DEPTH_BIAS = 3, - VK_DYNAMIC_STATE_BLEND_CONSTANTS = 4, - VK_DYNAMIC_STATE_DEPTH_BOUNDS = 5, - VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6, - VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7, - VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8, - VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000, - VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000, - VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000, - VK_DYNAMIC_STATE_BEGIN_RANGE = VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_END_RANGE = VK_DYNAMIC_STATE_STENCIL_REFERENCE, - VK_DYNAMIC_STATE_RANGE_SIZE = (VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1), - VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF -} VkDynamicState; - -typedef enum VkFilter { - VK_FILTER_NEAREST = 0, - VK_FILTER_LINEAR = 1, - VK_FILTER_CUBIC_IMG = 1000015000, - VK_FILTER_BEGIN_RANGE = VK_FILTER_NEAREST, - VK_FILTER_END_RANGE = VK_FILTER_LINEAR, - VK_FILTER_RANGE_SIZE = (VK_FILTER_LINEAR - VK_FILTER_NEAREST + 1), - VK_FILTER_MAX_ENUM = 0x7FFFFFFF -} VkFilter; - -typedef enum VkSamplerMipmapMode { - VK_SAMPLER_MIPMAP_MODE_NEAREST = 0, - VK_SAMPLER_MIPMAP_MODE_LINEAR = 1, - VK_SAMPLER_MIPMAP_MODE_BEGIN_RANGE = VK_SAMPLER_MIPMAP_MODE_NEAREST, - VK_SAMPLER_MIPMAP_MODE_END_RANGE = VK_SAMPLER_MIPMAP_MODE_LINEAR, - VK_SAMPLER_MIPMAP_MODE_RANGE_SIZE = (VK_SAMPLER_MIPMAP_MODE_LINEAR - VK_SAMPLER_MIPMAP_MODE_NEAREST + 1), - VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF -} VkSamplerMipmapMode; - -typedef enum VkSamplerAddressMode { - VK_SAMPLER_ADDRESS_MODE_REPEAT = 0, - VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, - VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, - VK_SAMPLER_ADDRESS_MODE_BEGIN_RANGE = VK_SAMPLER_ADDRESS_MODE_REPEAT, - VK_SAMPLER_ADDRESS_MODE_END_RANGE = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, - VK_SAMPLER_ADDRESS_MODE_RANGE_SIZE = (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER - VK_SAMPLER_ADDRESS_MODE_REPEAT + 1), - VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF -} VkSamplerAddressMode; - -typedef enum VkBorderColor { - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0, - VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1, - VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2, - VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3, - VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4, - VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5, - VK_BORDER_COLOR_BEGIN_RANGE = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, - VK_BORDER_COLOR_END_RANGE = VK_BORDER_COLOR_INT_OPAQUE_WHITE, - VK_BORDER_COLOR_RANGE_SIZE = (VK_BORDER_COLOR_INT_OPAQUE_WHITE - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK + 1), - VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF -} VkBorderColor; - -typedef enum VkDescriptorType { - VK_DESCRIPTOR_TYPE_SAMPLER = 0, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1, - VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2, - VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3, - VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4, - VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6, - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, - VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, - VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER, - VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, - VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1), - VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkDescriptorType; - -typedef enum VkAttachmentLoadOp { - VK_ATTACHMENT_LOAD_OP_LOAD = 0, - VK_ATTACHMENT_LOAD_OP_CLEAR = 1, - VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2, - VK_ATTACHMENT_LOAD_OP_BEGIN_RANGE = VK_ATTACHMENT_LOAD_OP_LOAD, - VK_ATTACHMENT_LOAD_OP_END_RANGE = VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_RANGE_SIZE = (VK_ATTACHMENT_LOAD_OP_DONT_CARE - VK_ATTACHMENT_LOAD_OP_LOAD + 1), - VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF -} VkAttachmentLoadOp; - -typedef enum VkAttachmentStoreOp { - VK_ATTACHMENT_STORE_OP_STORE = 0, - VK_ATTACHMENT_STORE_OP_DONT_CARE = 1, - VK_ATTACHMENT_STORE_OP_BEGIN_RANGE = VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_STORE_OP_END_RANGE = VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_RANGE_SIZE = (VK_ATTACHMENT_STORE_OP_DONT_CARE - VK_ATTACHMENT_STORE_OP_STORE + 1), - VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF -} VkAttachmentStoreOp; - -typedef enum VkPipelineBindPoint { - VK_PIPELINE_BIND_POINT_GRAPHICS = 0, - VK_PIPELINE_BIND_POINT_COMPUTE = 1, - VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS, - VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE, - VK_PIPELINE_BIND_POINT_RANGE_SIZE = (VK_PIPELINE_BIND_POINT_COMPUTE - VK_PIPELINE_BIND_POINT_GRAPHICS + 1), - VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF -} VkPipelineBindPoint; - -typedef enum VkCommandBufferLevel { - VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0, - VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1, - VK_COMMAND_BUFFER_LEVEL_BEGIN_RANGE = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - VK_COMMAND_BUFFER_LEVEL_END_RANGE = VK_COMMAND_BUFFER_LEVEL_SECONDARY, - VK_COMMAND_BUFFER_LEVEL_RANGE_SIZE = (VK_COMMAND_BUFFER_LEVEL_SECONDARY - VK_COMMAND_BUFFER_LEVEL_PRIMARY + 1), - VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF -} VkCommandBufferLevel; - -typedef enum VkIndexType { - VK_INDEX_TYPE_UINT16 = 0, - VK_INDEX_TYPE_UINT32 = 1, - VK_INDEX_TYPE_BEGIN_RANGE = VK_INDEX_TYPE_UINT16, - VK_INDEX_TYPE_END_RANGE = VK_INDEX_TYPE_UINT32, - VK_INDEX_TYPE_RANGE_SIZE = (VK_INDEX_TYPE_UINT32 - VK_INDEX_TYPE_UINT16 + 1), - VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkIndexType; - -typedef enum VkSubpassContents { - VK_SUBPASS_CONTENTS_INLINE = 0, - VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1, - VK_SUBPASS_CONTENTS_BEGIN_RANGE = VK_SUBPASS_CONTENTS_INLINE, - VK_SUBPASS_CONTENTS_END_RANGE = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, - VK_SUBPASS_CONTENTS_RANGE_SIZE = (VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS - VK_SUBPASS_CONTENTS_INLINE + 1), - VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF -} VkSubpassContents; - -typedef enum VkObjectType { - VK_OBJECT_TYPE_UNKNOWN = 0, - VK_OBJECT_TYPE_INSTANCE = 1, - VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2, - VK_OBJECT_TYPE_DEVICE = 3, - VK_OBJECT_TYPE_QUEUE = 4, - VK_OBJECT_TYPE_SEMAPHORE = 5, - VK_OBJECT_TYPE_COMMAND_BUFFER = 6, - VK_OBJECT_TYPE_FENCE = 7, - VK_OBJECT_TYPE_DEVICE_MEMORY = 8, - VK_OBJECT_TYPE_BUFFER = 9, - VK_OBJECT_TYPE_IMAGE = 10, - VK_OBJECT_TYPE_EVENT = 11, - VK_OBJECT_TYPE_QUERY_POOL = 12, - VK_OBJECT_TYPE_BUFFER_VIEW = 13, - VK_OBJECT_TYPE_IMAGE_VIEW = 14, - VK_OBJECT_TYPE_SHADER_MODULE = 15, - VK_OBJECT_TYPE_PIPELINE_CACHE = 16, - VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17, - VK_OBJECT_TYPE_RENDER_PASS = 18, - VK_OBJECT_TYPE_PIPELINE = 19, - VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20, - VK_OBJECT_TYPE_SAMPLER = 21, - VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22, - VK_OBJECT_TYPE_DESCRIPTOR_SET = 23, - VK_OBJECT_TYPE_FRAMEBUFFER = 24, - VK_OBJECT_TYPE_COMMAND_POOL = 25, - VK_OBJECT_TYPE_SURFACE_KHR = 1000000000, - VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000, - VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000, - VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001, - VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000, - VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = 1000085000, - VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000, - VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001, - VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = 1000156000, - VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000, - VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN, - VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_COMMAND_POOL, - VK_OBJECT_TYPE_RANGE_SIZE = (VK_OBJECT_TYPE_COMMAND_POOL - VK_OBJECT_TYPE_UNKNOWN + 1), - VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkObjectType; - -typedef VkFlags VkInstanceCreateFlags; - -typedef enum VkFormatFeatureFlagBits { - VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001, - VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0x00000002, - VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004, - VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008, - VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT = 0x00000010, - VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020, - VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT = 0x00000040, - VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT = 0x00000080, - VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100, - VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200, - VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0x00000400, - VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800, - VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000, - VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000, - VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = 0x00004000, - VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = 0x00008000, - VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = 0x00010000, - VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = 0x00020000, - VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = 0x00040000, - VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = 0x00080000, - VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = 0x00100000, - VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = 0x00200000, - VK_FORMAT_FEATURE_DISJOINT_BIT_KHR = 0x00400000, - VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR = 0x00800000, - VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkFormatFeatureFlagBits; -typedef VkFlags VkFormatFeatureFlags; - -typedef enum VkImageUsageFlagBits { - VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001, - VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002, - VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004, - VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, - VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, - VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkImageUsageFlagBits; -typedef VkFlags VkImageUsageFlags; - -typedef enum VkImageCreateFlagBits { - VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0x00000001, - VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, - VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004, - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008, - VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010, - VK_IMAGE_CREATE_BIND_SFR_BIT_KHX = 0x00000040, - VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = 0x00000020, - VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = 0x00000080, - VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR = 0x00000100, - VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000, - VK_IMAGE_CREATE_DISJOINT_BIT_KHR = 0x00000200, - VK_IMAGE_CREATE_ALIAS_BIT_KHR = 0x00000400, - VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkImageCreateFlagBits; -typedef VkFlags VkImageCreateFlags; - -typedef enum VkSampleCountFlagBits { - VK_SAMPLE_COUNT_1_BIT = 0x00000001, - VK_SAMPLE_COUNT_2_BIT = 0x00000002, - VK_SAMPLE_COUNT_4_BIT = 0x00000004, - VK_SAMPLE_COUNT_8_BIT = 0x00000008, - VK_SAMPLE_COUNT_16_BIT = 0x00000010, - VK_SAMPLE_COUNT_32_BIT = 0x00000020, - VK_SAMPLE_COUNT_64_BIT = 0x00000040, - VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkSampleCountFlagBits; -typedef VkFlags VkSampleCountFlags; - -typedef enum VkQueueFlagBits { - VK_QUEUE_GRAPHICS_BIT = 0x00000001, - VK_QUEUE_COMPUTE_BIT = 0x00000002, - VK_QUEUE_TRANSFER_BIT = 0x00000004, - VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, - VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkQueueFlagBits; -typedef VkFlags VkQueueFlags; - -typedef enum VkMemoryPropertyFlagBits { - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002, - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004, - VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008, - VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010, - VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkMemoryPropertyFlagBits; -typedef VkFlags VkMemoryPropertyFlags; - -typedef enum VkMemoryHeapFlagBits { - VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001, - VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHX = 0x00000002, - VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkMemoryHeapFlagBits; -typedef VkFlags VkMemoryHeapFlags; -typedef VkFlags VkDeviceCreateFlags; -typedef VkFlags VkDeviceQueueCreateFlags; - -typedef enum VkPipelineStageFlagBits { - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001, - VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004, - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008, - VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010, - VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020, - VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0x00000040, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100, - VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0x00000800, - VK_PIPELINE_STAGE_TRANSFER_BIT = 0x00001000, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0x00002000, - VK_PIPELINE_STAGE_HOST_BIT = 0x00004000, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000, - VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000, - VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkPipelineStageFlagBits; -typedef VkFlags VkPipelineStageFlags; -typedef VkFlags VkMemoryMapFlags; - -typedef enum VkImageAspectFlagBits { - VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001, - VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002, - VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004, - VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008, - VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = 0x00000010, - VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = 0x00000020, - VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = 0x00000040, - VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkImageAspectFlagBits; -typedef VkFlags VkImageAspectFlags; - -typedef enum VkSparseImageFormatFlagBits { - VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001, - VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 0x00000002, - VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 0x00000004, - VK_SPARSE_IMAGE_FORMAT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkSparseImageFormatFlagBits; -typedef VkFlags VkSparseImageFormatFlags; - -typedef enum VkSparseMemoryBindFlagBits { - VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001, - VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkSparseMemoryBindFlagBits; -typedef VkFlags VkSparseMemoryBindFlags; - -typedef enum VkFenceCreateFlagBits { - VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001, - VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkFenceCreateFlagBits; -typedef VkFlags VkFenceCreateFlags; -typedef VkFlags VkSemaphoreCreateFlags; -typedef VkFlags VkEventCreateFlags; -typedef VkFlags VkQueryPoolCreateFlags; - -typedef enum VkQueryPipelineStatisticFlagBits { - VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0x00000001, - VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT = 0x00000002, - VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT = 0x00000004, - VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT = 0x00000008, - VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT = 0x00000010, - VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT = 0x00000020, - VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT = 0x00000040, - VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 0x00000080, - VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100, - VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200, - VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400, - VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkQueryPipelineStatisticFlagBits; -typedef VkFlags VkQueryPipelineStatisticFlags; - -typedef enum VkQueryResultFlagBits { - VK_QUERY_RESULT_64_BIT = 0x00000001, - VK_QUERY_RESULT_WAIT_BIT = 0x00000002, - VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004, - VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008, - VK_QUERY_RESULT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkQueryResultFlagBits; -typedef VkFlags VkQueryResultFlags; - -typedef enum VkBufferCreateFlagBits { - VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0x00000001, - VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, - VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004, - VK_BUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkBufferCreateFlagBits; -typedef VkFlags VkBufferCreateFlags; - -typedef enum VkBufferUsageFlagBits { - VK_BUFFER_USAGE_TRANSFER_SRC_BIT = 0x00000001, - VK_BUFFER_USAGE_TRANSFER_DST_BIT = 0x00000002, - VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004, - VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0x00000008, - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0x00000010, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 0x00000020, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080, - VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100, - VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkBufferUsageFlagBits; -typedef VkFlags VkBufferUsageFlags; -typedef VkFlags VkBufferViewCreateFlags; -typedef VkFlags VkImageViewCreateFlags; -typedef VkFlags VkShaderModuleCreateFlags; -typedef VkFlags VkPipelineCacheCreateFlags; - -typedef enum VkPipelineCreateFlagBits { - VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001, - VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002, - VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, - VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHX = 0x00000008, - VK_PIPELINE_CREATE_DISPATCH_BASE_KHX = 0x00000010, - VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkPipelineCreateFlagBits; -typedef VkFlags VkPipelineCreateFlags; -typedef VkFlags VkPipelineShaderStageCreateFlags; - -typedef enum VkShaderStageFlagBits { - VK_SHADER_STAGE_VERTEX_BIT = 0x00000001, - VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002, - VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004, - VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008, - VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010, - VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020, - VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F, - VK_SHADER_STAGE_ALL = 0x7FFFFFFF, - VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkShaderStageFlagBits; -typedef VkFlags VkPipelineVertexInputStateCreateFlags; -typedef VkFlags VkPipelineInputAssemblyStateCreateFlags; -typedef VkFlags VkPipelineTessellationStateCreateFlags; -typedef VkFlags VkPipelineViewportStateCreateFlags; -typedef VkFlags VkPipelineRasterizationStateCreateFlags; - -typedef enum VkCullModeFlagBits { - VK_CULL_MODE_NONE = 0, - VK_CULL_MODE_FRONT_BIT = 0x00000001, - VK_CULL_MODE_BACK_BIT = 0x00000002, - VK_CULL_MODE_FRONT_AND_BACK = 0x00000003, - VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkCullModeFlagBits; -typedef VkFlags VkCullModeFlags; -typedef VkFlags VkPipelineMultisampleStateCreateFlags; -typedef VkFlags VkPipelineDepthStencilStateCreateFlags; -typedef VkFlags VkPipelineColorBlendStateCreateFlags; - -typedef enum VkColorComponentFlagBits { - VK_COLOR_COMPONENT_R_BIT = 0x00000001, - VK_COLOR_COMPONENT_G_BIT = 0x00000002, - VK_COLOR_COMPONENT_B_BIT = 0x00000004, - VK_COLOR_COMPONENT_A_BIT = 0x00000008, - VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkColorComponentFlagBits; -typedef VkFlags VkColorComponentFlags; -typedef VkFlags VkPipelineDynamicStateCreateFlags; -typedef VkFlags VkPipelineLayoutCreateFlags; -typedef VkFlags VkShaderStageFlags; -typedef VkFlags VkSamplerCreateFlags; - -typedef enum VkDescriptorSetLayoutCreateFlagBits { - VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001, - VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkDescriptorSetLayoutCreateFlagBits; -typedef VkFlags VkDescriptorSetLayoutCreateFlags; - -typedef enum VkDescriptorPoolCreateFlagBits { - VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001, - VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkDescriptorPoolCreateFlagBits; -typedef VkFlags VkDescriptorPoolCreateFlags; -typedef VkFlags VkDescriptorPoolResetFlags; -typedef VkFlags VkFramebufferCreateFlags; -typedef VkFlags VkRenderPassCreateFlags; - -typedef enum VkAttachmentDescriptionFlagBits { - VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001, - VK_ATTACHMENT_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkAttachmentDescriptionFlagBits; -typedef VkFlags VkAttachmentDescriptionFlags; - -typedef enum VkSubpassDescriptionFlagBits { - VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001, - VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002, - VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkSubpassDescriptionFlagBits; -typedef VkFlags VkSubpassDescriptionFlags; - -typedef enum VkAccessFlagBits { - VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001, - VK_ACCESS_INDEX_READ_BIT = 0x00000002, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004, - VK_ACCESS_UNIFORM_READ_BIT = 0x00000008, - VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010, - VK_ACCESS_SHADER_READ_BIT = 0x00000020, - VK_ACCESS_SHADER_WRITE_BIT = 0x00000040, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400, - VK_ACCESS_TRANSFER_READ_BIT = 0x00000800, - VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000, - VK_ACCESS_HOST_READ_BIT = 0x00002000, - VK_ACCESS_HOST_WRITE_BIT = 0x00004000, - VK_ACCESS_MEMORY_READ_BIT = 0x00008000, - VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, - VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000, - VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000, - VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, - VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkAccessFlagBits; -typedef VkFlags VkAccessFlags; - -typedef enum VkDependencyFlagBits { - VK_DEPENDENCY_BY_REGION_BIT = 0x00000001, - VK_DEPENDENCY_VIEW_LOCAL_BIT_KHX = 0x00000002, - VK_DEPENDENCY_DEVICE_GROUP_BIT_KHX = 0x00000004, - VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkDependencyFlagBits; -typedef VkFlags VkDependencyFlags; - -typedef enum VkCommandPoolCreateFlagBits { - VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001, - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002, - VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkCommandPoolCreateFlagBits; -typedef VkFlags VkCommandPoolCreateFlags; - -typedef enum VkCommandPoolResetFlagBits { - VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001, - VK_COMMAND_POOL_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkCommandPoolResetFlagBits; -typedef VkFlags VkCommandPoolResetFlags; - -typedef enum VkCommandBufferUsageFlagBits { - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001, - VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002, - VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004, - VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkCommandBufferUsageFlagBits; -typedef VkFlags VkCommandBufferUsageFlags; - -typedef enum VkQueryControlFlagBits { - VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001, - VK_QUERY_CONTROL_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkQueryControlFlagBits; -typedef VkFlags VkQueryControlFlags; - -typedef enum VkCommandBufferResetFlagBits { - VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001, - VK_COMMAND_BUFFER_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkCommandBufferResetFlagBits; -typedef VkFlags VkCommandBufferResetFlags; - -typedef enum VkStencilFaceFlagBits { - VK_STENCIL_FACE_FRONT_BIT = 0x00000001, - VK_STENCIL_FACE_BACK_BIT = 0x00000002, - VK_STENCIL_FRONT_AND_BACK = 0x00000003, - VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkStencilFaceFlagBits; -typedef VkFlags VkStencilFaceFlags; - -typedef struct VkApplicationInfo { - VkStructureType sType; - const void* pNext; - const char* pApplicationName; - uint32_t applicationVersion; - const char* pEngineName; - uint32_t engineVersion; - uint32_t apiVersion; -} VkApplicationInfo; - -typedef struct VkInstanceCreateInfo { - VkStructureType sType; - const void* pNext; - VkInstanceCreateFlags flags; - const VkApplicationInfo* pApplicationInfo; - uint32_t enabledLayerCount; - const char* const* ppEnabledLayerNames; - uint32_t enabledExtensionCount; - const char* const* ppEnabledExtensionNames; -} VkInstanceCreateInfo; - -typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)( - void* pUserData, - size_t size, - size_t alignment, - VkSystemAllocationScope allocationScope); - -typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)( - void* pUserData, - void* pOriginal, - size_t size, - size_t alignment, - VkSystemAllocationScope allocationScope); - -typedef void (VKAPI_PTR *PFN_vkFreeFunction)( - void* pUserData, - void* pMemory); - -typedef void (VKAPI_PTR *PFN_vkInternalAllocationNotification)( - void* pUserData, - size_t size, - VkInternalAllocationType allocationType, - VkSystemAllocationScope allocationScope); - -typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)( - void* pUserData, - size_t size, - VkInternalAllocationType allocationType, - VkSystemAllocationScope allocationScope); - -typedef struct VkAllocationCallbacks { - void* pUserData; - PFN_vkAllocationFunction pfnAllocation; - PFN_vkReallocationFunction pfnReallocation; - PFN_vkFreeFunction pfnFree; - PFN_vkInternalAllocationNotification pfnInternalAllocation; - PFN_vkInternalFreeNotification pfnInternalFree; -} VkAllocationCallbacks; - -typedef struct VkPhysicalDeviceFeatures { - VkBool32 robustBufferAccess; - VkBool32 fullDrawIndexUint32; - VkBool32 imageCubeArray; - VkBool32 independentBlend; - VkBool32 geometryShader; - VkBool32 tessellationShader; - VkBool32 sampleRateShading; - VkBool32 dualSrcBlend; - VkBool32 logicOp; - VkBool32 multiDrawIndirect; - VkBool32 drawIndirectFirstInstance; - VkBool32 depthClamp; - VkBool32 depthBiasClamp; - VkBool32 fillModeNonSolid; - VkBool32 depthBounds; - VkBool32 wideLines; - VkBool32 largePoints; - VkBool32 alphaToOne; - VkBool32 multiViewport; - VkBool32 samplerAnisotropy; - VkBool32 textureCompressionETC2; - VkBool32 textureCompressionASTC_LDR; - VkBool32 textureCompressionBC; - VkBool32 occlusionQueryPrecise; - VkBool32 pipelineStatisticsQuery; - VkBool32 vertexPipelineStoresAndAtomics; - VkBool32 fragmentStoresAndAtomics; - VkBool32 shaderTessellationAndGeometryPointSize; - VkBool32 shaderImageGatherExtended; - VkBool32 shaderStorageImageExtendedFormats; - VkBool32 shaderStorageImageMultisample; - VkBool32 shaderStorageImageReadWithoutFormat; - VkBool32 shaderStorageImageWriteWithoutFormat; - VkBool32 shaderUniformBufferArrayDynamicIndexing; - VkBool32 shaderSampledImageArrayDynamicIndexing; - VkBool32 shaderStorageBufferArrayDynamicIndexing; - VkBool32 shaderStorageImageArrayDynamicIndexing; - VkBool32 shaderClipDistance; - VkBool32 shaderCullDistance; - VkBool32 shaderFloat64; - VkBool32 shaderInt64; - VkBool32 shaderInt16; - VkBool32 shaderResourceResidency; - VkBool32 shaderResourceMinLod; - VkBool32 sparseBinding; - VkBool32 sparseResidencyBuffer; - VkBool32 sparseResidencyImage2D; - VkBool32 sparseResidencyImage3D; - VkBool32 sparseResidency2Samples; - VkBool32 sparseResidency4Samples; - VkBool32 sparseResidency8Samples; - VkBool32 sparseResidency16Samples; - VkBool32 sparseResidencyAliased; - VkBool32 variableMultisampleRate; - VkBool32 inheritedQueries; -} VkPhysicalDeviceFeatures; - -typedef struct VkFormatProperties { - VkFormatFeatureFlags linearTilingFeatures; - VkFormatFeatureFlags optimalTilingFeatures; - VkFormatFeatureFlags bufferFeatures; -} VkFormatProperties; - -typedef struct VkExtent3D { - uint32_t width; - uint32_t height; - uint32_t depth; -} VkExtent3D; - -typedef struct VkImageFormatProperties { - VkExtent3D maxExtent; - uint32_t maxMipLevels; - uint32_t maxArrayLayers; - VkSampleCountFlags sampleCounts; - VkDeviceSize maxResourceSize; -} VkImageFormatProperties; - -typedef struct VkPhysicalDeviceLimits { - uint32_t maxImageDimension1D; - uint32_t maxImageDimension2D; - uint32_t maxImageDimension3D; - uint32_t maxImageDimensionCube; - uint32_t maxImageArrayLayers; - uint32_t maxTexelBufferElements; - uint32_t maxUniformBufferRange; - uint32_t maxStorageBufferRange; - uint32_t maxPushConstantsSize; - uint32_t maxMemoryAllocationCount; - uint32_t maxSamplerAllocationCount; - VkDeviceSize bufferImageGranularity; - VkDeviceSize sparseAddressSpaceSize; - uint32_t maxBoundDescriptorSets; - uint32_t maxPerStageDescriptorSamplers; - uint32_t maxPerStageDescriptorUniformBuffers; - uint32_t maxPerStageDescriptorStorageBuffers; - uint32_t maxPerStageDescriptorSampledImages; - uint32_t maxPerStageDescriptorStorageImages; - uint32_t maxPerStageDescriptorInputAttachments; - uint32_t maxPerStageResources; - uint32_t maxDescriptorSetSamplers; - uint32_t maxDescriptorSetUniformBuffers; - uint32_t maxDescriptorSetUniformBuffersDynamic; - uint32_t maxDescriptorSetStorageBuffers; - uint32_t maxDescriptorSetStorageBuffersDynamic; - uint32_t maxDescriptorSetSampledImages; - uint32_t maxDescriptorSetStorageImages; - uint32_t maxDescriptorSetInputAttachments; - uint32_t maxVertexInputAttributes; - uint32_t maxVertexInputBindings; - uint32_t maxVertexInputAttributeOffset; - uint32_t maxVertexInputBindingStride; - uint32_t maxVertexOutputComponents; - uint32_t maxTessellationGenerationLevel; - uint32_t maxTessellationPatchSize; - uint32_t maxTessellationControlPerVertexInputComponents; - uint32_t maxTessellationControlPerVertexOutputComponents; - uint32_t maxTessellationControlPerPatchOutputComponents; - uint32_t maxTessellationControlTotalOutputComponents; - uint32_t maxTessellationEvaluationInputComponents; - uint32_t maxTessellationEvaluationOutputComponents; - uint32_t maxGeometryShaderInvocations; - uint32_t maxGeometryInputComponents; - uint32_t maxGeometryOutputComponents; - uint32_t maxGeometryOutputVertices; - uint32_t maxGeometryTotalOutputComponents; - uint32_t maxFragmentInputComponents; - uint32_t maxFragmentOutputAttachments; - uint32_t maxFragmentDualSrcAttachments; - uint32_t maxFragmentCombinedOutputResources; - uint32_t maxComputeSharedMemorySize; - uint32_t maxComputeWorkGroupCount[3]; - uint32_t maxComputeWorkGroupInvocations; - uint32_t maxComputeWorkGroupSize[3]; - uint32_t subPixelPrecisionBits; - uint32_t subTexelPrecisionBits; - uint32_t mipmapPrecisionBits; - uint32_t maxDrawIndexedIndexValue; - uint32_t maxDrawIndirectCount; - float maxSamplerLodBias; - float maxSamplerAnisotropy; - uint32_t maxViewports; - uint32_t maxViewportDimensions[2]; - float viewportBoundsRange[2]; - uint32_t viewportSubPixelBits; - size_t minMemoryMapAlignment; - VkDeviceSize minTexelBufferOffsetAlignment; - VkDeviceSize minUniformBufferOffsetAlignment; - VkDeviceSize minStorageBufferOffsetAlignment; - int32_t minTexelOffset; - uint32_t maxTexelOffset; - int32_t minTexelGatherOffset; - uint32_t maxTexelGatherOffset; - float minInterpolationOffset; - float maxInterpolationOffset; - uint32_t subPixelInterpolationOffsetBits; - uint32_t maxFramebufferWidth; - uint32_t maxFramebufferHeight; - uint32_t maxFramebufferLayers; - VkSampleCountFlags framebufferColorSampleCounts; - VkSampleCountFlags framebufferDepthSampleCounts; - VkSampleCountFlags framebufferStencilSampleCounts; - VkSampleCountFlags framebufferNoAttachmentsSampleCounts; - uint32_t maxColorAttachments; - VkSampleCountFlags sampledImageColorSampleCounts; - VkSampleCountFlags sampledImageIntegerSampleCounts; - VkSampleCountFlags sampledImageDepthSampleCounts; - VkSampleCountFlags sampledImageStencilSampleCounts; - VkSampleCountFlags storageImageSampleCounts; - uint32_t maxSampleMaskWords; - VkBool32 timestampComputeAndGraphics; - float timestampPeriod; - uint32_t maxClipDistances; - uint32_t maxCullDistances; - uint32_t maxCombinedClipAndCullDistances; - uint32_t discreteQueuePriorities; - float pointSizeRange[2]; - float lineWidthRange[2]; - float pointSizeGranularity; - float lineWidthGranularity; - VkBool32 strictLines; - VkBool32 standardSampleLocations; - VkDeviceSize optimalBufferCopyOffsetAlignment; - VkDeviceSize optimalBufferCopyRowPitchAlignment; - VkDeviceSize nonCoherentAtomSize; -} VkPhysicalDeviceLimits; - -typedef struct VkPhysicalDeviceSparseProperties { - VkBool32 residencyStandard2DBlockShape; - VkBool32 residencyStandard2DMultisampleBlockShape; - VkBool32 residencyStandard3DBlockShape; - VkBool32 residencyAlignedMipSize; - VkBool32 residencyNonResidentStrict; -} VkPhysicalDeviceSparseProperties; - -typedef struct VkPhysicalDeviceProperties { - uint32_t apiVersion; - uint32_t driverVersion; - uint32_t vendorID; - uint32_t deviceID; - VkPhysicalDeviceType deviceType; - char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; - uint8_t pipelineCacheUUID[VK_UUID_SIZE]; - VkPhysicalDeviceLimits limits; - VkPhysicalDeviceSparseProperties sparseProperties; -} VkPhysicalDeviceProperties; - -typedef struct VkQueueFamilyProperties { - VkQueueFlags queueFlags; - uint32_t queueCount; - uint32_t timestampValidBits; - VkExtent3D minImageTransferGranularity; -} VkQueueFamilyProperties; - -typedef struct VkMemoryType { - VkMemoryPropertyFlags propertyFlags; - uint32_t heapIndex; -} VkMemoryType; - -typedef struct VkMemoryHeap { - VkDeviceSize size; - VkMemoryHeapFlags flags; -} VkMemoryHeap; - -typedef struct VkPhysicalDeviceMemoryProperties { - uint32_t memoryTypeCount; - VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES]; - uint32_t memoryHeapCount; - VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS]; -} VkPhysicalDeviceMemoryProperties; - -typedef void (VKAPI_PTR *PFN_vkVoidFunction)(void); -typedef struct VkDeviceQueueCreateInfo { - VkStructureType sType; - const void* pNext; - VkDeviceQueueCreateFlags flags; - uint32_t queueFamilyIndex; - uint32_t queueCount; - const float* pQueuePriorities; -} VkDeviceQueueCreateInfo; - -typedef struct VkDeviceCreateInfo { - VkStructureType sType; - const void* pNext; - VkDeviceCreateFlags flags; - uint32_t queueCreateInfoCount; - const VkDeviceQueueCreateInfo* pQueueCreateInfos; - uint32_t enabledLayerCount; - const char* const* ppEnabledLayerNames; - uint32_t enabledExtensionCount; - const char* const* ppEnabledExtensionNames; - const VkPhysicalDeviceFeatures* pEnabledFeatures; -} VkDeviceCreateInfo; - -typedef struct VkExtensionProperties { - char extensionName[VK_MAX_EXTENSION_NAME_SIZE]; - uint32_t specVersion; -} VkExtensionProperties; - -typedef struct VkLayerProperties { - char layerName[VK_MAX_EXTENSION_NAME_SIZE]; - uint32_t specVersion; - uint32_t implementationVersion; - char description[VK_MAX_DESCRIPTION_SIZE]; -} VkLayerProperties; - -typedef struct VkSubmitInfo { - VkStructureType sType; - const void* pNext; - uint32_t waitSemaphoreCount; - const VkSemaphore* pWaitSemaphores; - const VkPipelineStageFlags* pWaitDstStageMask; - uint32_t commandBufferCount; - const VkCommandBuffer* pCommandBuffers; - uint32_t signalSemaphoreCount; - const VkSemaphore* pSignalSemaphores; -} VkSubmitInfo; - -typedef struct VkMemoryAllocateInfo { - VkStructureType sType; - const void* pNext; - VkDeviceSize allocationSize; - uint32_t memoryTypeIndex; -} VkMemoryAllocateInfo; - -typedef struct VkMappedMemoryRange { - VkStructureType sType; - const void* pNext; - VkDeviceMemory memory; - VkDeviceSize offset; - VkDeviceSize size; -} VkMappedMemoryRange; - -typedef struct VkMemoryRequirements { - VkDeviceSize size; - VkDeviceSize alignment; - uint32_t memoryTypeBits; -} VkMemoryRequirements; - -typedef struct VkSparseImageFormatProperties { - VkImageAspectFlags aspectMask; - VkExtent3D imageGranularity; - VkSparseImageFormatFlags flags; -} VkSparseImageFormatProperties; - -typedef struct VkSparseImageMemoryRequirements { - VkSparseImageFormatProperties formatProperties; - uint32_t imageMipTailFirstLod; - VkDeviceSize imageMipTailSize; - VkDeviceSize imageMipTailOffset; - VkDeviceSize imageMipTailStride; -} VkSparseImageMemoryRequirements; - -typedef struct VkSparseMemoryBind { - VkDeviceSize resourceOffset; - VkDeviceSize size; - VkDeviceMemory memory; - VkDeviceSize memoryOffset; - VkSparseMemoryBindFlags flags; -} VkSparseMemoryBind; - -typedef struct VkSparseBufferMemoryBindInfo { - VkBuffer buffer; - uint32_t bindCount; - const VkSparseMemoryBind* pBinds; -} VkSparseBufferMemoryBindInfo; - -typedef struct VkSparseImageOpaqueMemoryBindInfo { - VkImage image; - uint32_t bindCount; - const VkSparseMemoryBind* pBinds; -} VkSparseImageOpaqueMemoryBindInfo; - -typedef struct VkImageSubresource { - VkImageAspectFlags aspectMask; - uint32_t mipLevel; - uint32_t arrayLayer; -} VkImageSubresource; - -typedef struct VkOffset3D { - int32_t x; - int32_t y; - int32_t z; -} VkOffset3D; - -typedef struct VkSparseImageMemoryBind { - VkImageSubresource subresource; - VkOffset3D offset; - VkExtent3D extent; - VkDeviceMemory memory; - VkDeviceSize memoryOffset; - VkSparseMemoryBindFlags flags; -} VkSparseImageMemoryBind; - -typedef struct VkSparseImageMemoryBindInfo { - VkImage image; - uint32_t bindCount; - const VkSparseImageMemoryBind* pBinds; -} VkSparseImageMemoryBindInfo; - -typedef struct VkBindSparseInfo { - VkStructureType sType; - const void* pNext; - uint32_t waitSemaphoreCount; - const VkSemaphore* pWaitSemaphores; - uint32_t bufferBindCount; - const VkSparseBufferMemoryBindInfo* pBufferBinds; - uint32_t imageOpaqueBindCount; - const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds; - uint32_t imageBindCount; - const VkSparseImageMemoryBindInfo* pImageBinds; - uint32_t signalSemaphoreCount; - const VkSemaphore* pSignalSemaphores; -} VkBindSparseInfo; - -typedef struct VkFenceCreateInfo { - VkStructureType sType; - const void* pNext; - VkFenceCreateFlags flags; -} VkFenceCreateInfo; - -typedef struct VkSemaphoreCreateInfo { - VkStructureType sType; - const void* pNext; - VkSemaphoreCreateFlags flags; -} VkSemaphoreCreateInfo; - -typedef struct VkEventCreateInfo { - VkStructureType sType; - const void* pNext; - VkEventCreateFlags flags; -} VkEventCreateInfo; - -typedef struct VkQueryPoolCreateInfo { - VkStructureType sType; - const void* pNext; - VkQueryPoolCreateFlags flags; - VkQueryType queryType; - uint32_t queryCount; - VkQueryPipelineStatisticFlags pipelineStatistics; -} VkQueryPoolCreateInfo; - -typedef struct VkBufferCreateInfo { - VkStructureType sType; - const void* pNext; - VkBufferCreateFlags flags; - VkDeviceSize size; - VkBufferUsageFlags usage; - VkSharingMode sharingMode; - uint32_t queueFamilyIndexCount; - const uint32_t* pQueueFamilyIndices; -} VkBufferCreateInfo; - -typedef struct VkBufferViewCreateInfo { - VkStructureType sType; - const void* pNext; - VkBufferViewCreateFlags flags; - VkBuffer buffer; - VkFormat format; - VkDeviceSize offset; - VkDeviceSize range; -} VkBufferViewCreateInfo; - -typedef struct VkImageCreateInfo { - VkStructureType sType; - const void* pNext; - VkImageCreateFlags flags; - VkImageType imageType; - VkFormat format; - VkExtent3D extent; - uint32_t mipLevels; - uint32_t arrayLayers; - VkSampleCountFlagBits samples; - VkImageTiling tiling; - VkImageUsageFlags usage; - VkSharingMode sharingMode; - uint32_t queueFamilyIndexCount; - const uint32_t* pQueueFamilyIndices; - VkImageLayout initialLayout; -} VkImageCreateInfo; - -typedef struct VkSubresourceLayout { - VkDeviceSize offset; - VkDeviceSize size; - VkDeviceSize rowPitch; - VkDeviceSize arrayPitch; - VkDeviceSize depthPitch; -} VkSubresourceLayout; - -typedef struct VkComponentMapping { - VkComponentSwizzle r; - VkComponentSwizzle g; - VkComponentSwizzle b; - VkComponentSwizzle a; -} VkComponentMapping; - -typedef struct VkImageSubresourceRange { - VkImageAspectFlags aspectMask; - uint32_t baseMipLevel; - uint32_t levelCount; - uint32_t baseArrayLayer; - uint32_t layerCount; -} VkImageSubresourceRange; - -typedef struct VkImageViewCreateInfo { - VkStructureType sType; - const void* pNext; - VkImageViewCreateFlags flags; - VkImage image; - VkImageViewType viewType; - VkFormat format; - VkComponentMapping components; - VkImageSubresourceRange subresourceRange; -} VkImageViewCreateInfo; - -typedef struct VkShaderModuleCreateInfo { - VkStructureType sType; - const void* pNext; - VkShaderModuleCreateFlags flags; - size_t codeSize; - const uint32_t* pCode; -} VkShaderModuleCreateInfo; - -typedef struct VkPipelineCacheCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineCacheCreateFlags flags; - size_t initialDataSize; - const void* pInitialData; -} VkPipelineCacheCreateInfo; - -typedef struct VkSpecializationMapEntry { - uint32_t constantID; - uint32_t offset; - size_t size; -} VkSpecializationMapEntry; - -typedef struct VkSpecializationInfo { - uint32_t mapEntryCount; - const VkSpecializationMapEntry* pMapEntries; - size_t dataSize; - const void* pData; -} VkSpecializationInfo; - -typedef struct VkPipelineShaderStageCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineShaderStageCreateFlags flags; - VkShaderStageFlagBits stage; - VkShaderModule module; - const char* pName; - const VkSpecializationInfo* pSpecializationInfo; -} VkPipelineShaderStageCreateInfo; - -typedef struct VkVertexInputBindingDescription { - uint32_t binding; - uint32_t stride; - VkVertexInputRate inputRate; -} VkVertexInputBindingDescription; - -typedef struct VkVertexInputAttributeDescription { - uint32_t location; - uint32_t binding; - VkFormat format; - uint32_t offset; -} VkVertexInputAttributeDescription; - -typedef struct VkPipelineVertexInputStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineVertexInputStateCreateFlags flags; - uint32_t vertexBindingDescriptionCount; - const VkVertexInputBindingDescription* pVertexBindingDescriptions; - uint32_t vertexAttributeDescriptionCount; - const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; -} VkPipelineVertexInputStateCreateInfo; - -typedef struct VkPipelineInputAssemblyStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineInputAssemblyStateCreateFlags flags; - VkPrimitiveTopology topology; - VkBool32 primitiveRestartEnable; -} VkPipelineInputAssemblyStateCreateInfo; - -typedef struct VkPipelineTessellationStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineTessellationStateCreateFlags flags; - uint32_t patchControlPoints; -} VkPipelineTessellationStateCreateInfo; - -typedef struct VkViewport { - float x; - float y; - float width; - float height; - float minDepth; - float maxDepth; -} VkViewport; - -typedef struct VkOffset2D { - int32_t x; - int32_t y; -} VkOffset2D; - -typedef struct VkExtent2D { - uint32_t width; - uint32_t height; -} VkExtent2D; - -typedef struct VkRect2D { - VkOffset2D offset; - VkExtent2D extent; -} VkRect2D; - -typedef struct VkPipelineViewportStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineViewportStateCreateFlags flags; - uint32_t viewportCount; - const VkViewport* pViewports; - uint32_t scissorCount; - const VkRect2D* pScissors; -} VkPipelineViewportStateCreateInfo; - -typedef struct VkPipelineRasterizationStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineRasterizationStateCreateFlags flags; - VkBool32 depthClampEnable; - VkBool32 rasterizerDiscardEnable; - VkPolygonMode polygonMode; - VkCullModeFlags cullMode; - VkFrontFace frontFace; - VkBool32 depthBiasEnable; - float depthBiasConstantFactor; - float depthBiasClamp; - float depthBiasSlopeFactor; - float lineWidth; -} VkPipelineRasterizationStateCreateInfo; - -typedef struct VkPipelineMultisampleStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineMultisampleStateCreateFlags flags; - VkSampleCountFlagBits rasterizationSamples; - VkBool32 sampleShadingEnable; - float minSampleShading; - const VkSampleMask* pSampleMask; - VkBool32 alphaToCoverageEnable; - VkBool32 alphaToOneEnable; -} VkPipelineMultisampleStateCreateInfo; - -typedef struct VkStencilOpState { - VkStencilOp failOp; - VkStencilOp passOp; - VkStencilOp depthFailOp; - VkCompareOp compareOp; - uint32_t compareMask; - uint32_t writeMask; - uint32_t reference; -} VkStencilOpState; - -typedef struct VkPipelineDepthStencilStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineDepthStencilStateCreateFlags flags; - VkBool32 depthTestEnable; - VkBool32 depthWriteEnable; - VkCompareOp depthCompareOp; - VkBool32 depthBoundsTestEnable; - VkBool32 stencilTestEnable; - VkStencilOpState front; - VkStencilOpState back; - float minDepthBounds; - float maxDepthBounds; -} VkPipelineDepthStencilStateCreateInfo; - -typedef struct VkPipelineColorBlendAttachmentState { - VkBool32 blendEnable; - VkBlendFactor srcColorBlendFactor; - VkBlendFactor dstColorBlendFactor; - VkBlendOp colorBlendOp; - VkBlendFactor srcAlphaBlendFactor; - VkBlendFactor dstAlphaBlendFactor; - VkBlendOp alphaBlendOp; - VkColorComponentFlags colorWriteMask; -} VkPipelineColorBlendAttachmentState; - -typedef struct VkPipelineColorBlendStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineColorBlendStateCreateFlags flags; - VkBool32 logicOpEnable; - VkLogicOp logicOp; - uint32_t attachmentCount; - const VkPipelineColorBlendAttachmentState* pAttachments; - float blendConstants[4]; -} VkPipelineColorBlendStateCreateInfo; - -typedef struct VkPipelineDynamicStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineDynamicStateCreateFlags flags; - uint32_t dynamicStateCount; - const VkDynamicState* pDynamicStates; -} VkPipelineDynamicStateCreateInfo; - -typedef struct VkGraphicsPipelineCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineCreateFlags flags; - uint32_t stageCount; - const VkPipelineShaderStageCreateInfo* pStages; - const VkPipelineVertexInputStateCreateInfo* pVertexInputState; - const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; - const VkPipelineTessellationStateCreateInfo* pTessellationState; - const VkPipelineViewportStateCreateInfo* pViewportState; - const VkPipelineRasterizationStateCreateInfo* pRasterizationState; - const VkPipelineMultisampleStateCreateInfo* pMultisampleState; - const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; - const VkPipelineColorBlendStateCreateInfo* pColorBlendState; - const VkPipelineDynamicStateCreateInfo* pDynamicState; - VkPipelineLayout layout; - VkRenderPass renderPass; - uint32_t subpass; - VkPipeline basePipelineHandle; - int32_t basePipelineIndex; -} VkGraphicsPipelineCreateInfo; - -typedef struct VkComputePipelineCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineCreateFlags flags; - VkPipelineShaderStageCreateInfo stage; - VkPipelineLayout layout; - VkPipeline basePipelineHandle; - int32_t basePipelineIndex; -} VkComputePipelineCreateInfo; - -typedef struct VkPushConstantRange { - VkShaderStageFlags stageFlags; - uint32_t offset; - uint32_t size; -} VkPushConstantRange; - -typedef struct VkPipelineLayoutCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineLayoutCreateFlags flags; - uint32_t setLayoutCount; - const VkDescriptorSetLayout* pSetLayouts; - uint32_t pushConstantRangeCount; - const VkPushConstantRange* pPushConstantRanges; -} VkPipelineLayoutCreateInfo; - -typedef struct VkSamplerCreateInfo { - VkStructureType sType; - const void* pNext; - VkSamplerCreateFlags flags; - VkFilter magFilter; - VkFilter minFilter; - VkSamplerMipmapMode mipmapMode; - VkSamplerAddressMode addressModeU; - VkSamplerAddressMode addressModeV; - VkSamplerAddressMode addressModeW; - float mipLodBias; - VkBool32 anisotropyEnable; - float maxAnisotropy; - VkBool32 compareEnable; - VkCompareOp compareOp; - float minLod; - float maxLod; - VkBorderColor borderColor; - VkBool32 unnormalizedCoordinates; -} VkSamplerCreateInfo; - -typedef struct VkDescriptorSetLayoutBinding { - uint32_t binding; - VkDescriptorType descriptorType; - uint32_t descriptorCount; - VkShaderStageFlags stageFlags; - const VkSampler* pImmutableSamplers; -} VkDescriptorSetLayoutBinding; - -typedef struct VkDescriptorSetLayoutCreateInfo { - VkStructureType sType; - const void* pNext; - VkDescriptorSetLayoutCreateFlags flags; - uint32_t bindingCount; - const VkDescriptorSetLayoutBinding* pBindings; -} VkDescriptorSetLayoutCreateInfo; - -typedef struct VkDescriptorPoolSize { - VkDescriptorType type; - uint32_t descriptorCount; -} VkDescriptorPoolSize; - -typedef struct VkDescriptorPoolCreateInfo { - VkStructureType sType; - const void* pNext; - VkDescriptorPoolCreateFlags flags; - uint32_t maxSets; - uint32_t poolSizeCount; - const VkDescriptorPoolSize* pPoolSizes; -} VkDescriptorPoolCreateInfo; - -typedef struct VkDescriptorSetAllocateInfo { - VkStructureType sType; - const void* pNext; - VkDescriptorPool descriptorPool; - uint32_t descriptorSetCount; - const VkDescriptorSetLayout* pSetLayouts; -} VkDescriptorSetAllocateInfo; - -typedef struct VkDescriptorImageInfo { - VkSampler sampler; - VkImageView imageView; - VkImageLayout imageLayout; -} VkDescriptorImageInfo; - -typedef struct VkDescriptorBufferInfo { - VkBuffer buffer; - VkDeviceSize offset; - VkDeviceSize range; -} VkDescriptorBufferInfo; - -typedef struct VkWriteDescriptorSet { - VkStructureType sType; - const void* pNext; - VkDescriptorSet dstSet; - uint32_t dstBinding; - uint32_t dstArrayElement; - uint32_t descriptorCount; - VkDescriptorType descriptorType; - const VkDescriptorImageInfo* pImageInfo; - const VkDescriptorBufferInfo* pBufferInfo; - const VkBufferView* pTexelBufferView; -} VkWriteDescriptorSet; - -typedef struct VkCopyDescriptorSet { - VkStructureType sType; - const void* pNext; - VkDescriptorSet srcSet; - uint32_t srcBinding; - uint32_t srcArrayElement; - VkDescriptorSet dstSet; - uint32_t dstBinding; - uint32_t dstArrayElement; - uint32_t descriptorCount; -} VkCopyDescriptorSet; - -typedef struct VkFramebufferCreateInfo { - VkStructureType sType; - const void* pNext; - VkFramebufferCreateFlags flags; - VkRenderPass renderPass; - uint32_t attachmentCount; - const VkImageView* pAttachments; - uint32_t width; - uint32_t height; - uint32_t layers; -} VkFramebufferCreateInfo; - -typedef struct VkAttachmentDescription { - VkAttachmentDescriptionFlags flags; - VkFormat format; - VkSampleCountFlagBits samples; - VkAttachmentLoadOp loadOp; - VkAttachmentStoreOp storeOp; - VkAttachmentLoadOp stencilLoadOp; - VkAttachmentStoreOp stencilStoreOp; - VkImageLayout initialLayout; - VkImageLayout finalLayout; -} VkAttachmentDescription; - -typedef struct VkAttachmentReference { - uint32_t attachment; - VkImageLayout layout; -} VkAttachmentReference; - -typedef struct VkSubpassDescription { - VkSubpassDescriptionFlags flags; - VkPipelineBindPoint pipelineBindPoint; - uint32_t inputAttachmentCount; - const VkAttachmentReference* pInputAttachments; - uint32_t colorAttachmentCount; - const VkAttachmentReference* pColorAttachments; - const VkAttachmentReference* pResolveAttachments; - const VkAttachmentReference* pDepthStencilAttachment; - uint32_t preserveAttachmentCount; - const uint32_t* pPreserveAttachments; -} VkSubpassDescription; - -typedef struct VkSubpassDependency { - uint32_t srcSubpass; - uint32_t dstSubpass; - VkPipelineStageFlags srcStageMask; - VkPipelineStageFlags dstStageMask; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; - VkDependencyFlags dependencyFlags; -} VkSubpassDependency; - -typedef struct VkRenderPassCreateInfo { - VkStructureType sType; - const void* pNext; - VkRenderPassCreateFlags flags; - uint32_t attachmentCount; - const VkAttachmentDescription* pAttachments; - uint32_t subpassCount; - const VkSubpassDescription* pSubpasses; - uint32_t dependencyCount; - const VkSubpassDependency* pDependencies; -} VkRenderPassCreateInfo; - -typedef struct VkCommandPoolCreateInfo { - VkStructureType sType; - const void* pNext; - VkCommandPoolCreateFlags flags; - uint32_t queueFamilyIndex; -} VkCommandPoolCreateInfo; - -typedef struct VkCommandBufferAllocateInfo { - VkStructureType sType; - const void* pNext; - VkCommandPool commandPool; - VkCommandBufferLevel level; - uint32_t commandBufferCount; -} VkCommandBufferAllocateInfo; - -typedef struct VkCommandBufferInheritanceInfo { - VkStructureType sType; - const void* pNext; - VkRenderPass renderPass; - uint32_t subpass; - VkFramebuffer framebuffer; - VkBool32 occlusionQueryEnable; - VkQueryControlFlags queryFlags; - VkQueryPipelineStatisticFlags pipelineStatistics; -} VkCommandBufferInheritanceInfo; - -typedef struct VkCommandBufferBeginInfo { - VkStructureType sType; - const void* pNext; - VkCommandBufferUsageFlags flags; - const VkCommandBufferInheritanceInfo* pInheritanceInfo; -} VkCommandBufferBeginInfo; - -typedef struct VkBufferCopy { - VkDeviceSize srcOffset; - VkDeviceSize dstOffset; - VkDeviceSize size; -} VkBufferCopy; - -typedef struct VkImageSubresourceLayers { - VkImageAspectFlags aspectMask; - uint32_t mipLevel; - uint32_t baseArrayLayer; - uint32_t layerCount; -} VkImageSubresourceLayers; - -typedef struct VkImageCopy { - VkImageSubresourceLayers srcSubresource; - VkOffset3D srcOffset; - VkImageSubresourceLayers dstSubresource; - VkOffset3D dstOffset; - VkExtent3D extent; -} VkImageCopy; - -typedef struct VkImageBlit { - VkImageSubresourceLayers srcSubresource; - VkOffset3D srcOffsets[2]; - VkImageSubresourceLayers dstSubresource; - VkOffset3D dstOffsets[2]; -} VkImageBlit; - -typedef struct VkBufferImageCopy { - VkDeviceSize bufferOffset; - uint32_t bufferRowLength; - uint32_t bufferImageHeight; - VkImageSubresourceLayers imageSubresource; - VkOffset3D imageOffset; - VkExtent3D imageExtent; -} VkBufferImageCopy; - -typedef union VkClearColorValue { - float float32[4]; - int32_t int32[4]; - uint32_t uint32[4]; -} VkClearColorValue; - -typedef struct VkClearDepthStencilValue { - float depth; - uint32_t stencil; -} VkClearDepthStencilValue; - -typedef union VkClearValue { - VkClearColorValue color; - VkClearDepthStencilValue depthStencil; -} VkClearValue; - -typedef struct VkClearAttachment { - VkImageAspectFlags aspectMask; - uint32_t colorAttachment; - VkClearValue clearValue; -} VkClearAttachment; - -typedef struct VkClearRect { - VkRect2D rect; - uint32_t baseArrayLayer; - uint32_t layerCount; -} VkClearRect; - -typedef struct VkImageResolve { - VkImageSubresourceLayers srcSubresource; - VkOffset3D srcOffset; - VkImageSubresourceLayers dstSubresource; - VkOffset3D dstOffset; - VkExtent3D extent; -} VkImageResolve; - -typedef struct VkMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; -} VkMemoryBarrier; - -typedef struct VkBufferMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; - uint32_t srcQueueFamilyIndex; - uint32_t dstQueueFamilyIndex; - VkBuffer buffer; - VkDeviceSize offset; - VkDeviceSize size; -} VkBufferMemoryBarrier; - -typedef struct VkImageMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; - VkImageLayout oldLayout; - VkImageLayout newLayout; - uint32_t srcQueueFamilyIndex; - uint32_t dstQueueFamilyIndex; - VkImage image; - VkImageSubresourceRange subresourceRange; -} VkImageMemoryBarrier; - -typedef struct VkRenderPassBeginInfo { - VkStructureType sType; - const void* pNext; - VkRenderPass renderPass; - VkFramebuffer framebuffer; - VkRect2D renderArea; - uint32_t clearValueCount; - const VkClearValue* pClearValues; -} VkRenderPassBeginInfo; - -typedef struct VkDispatchIndirectCommand { - uint32_t x; - uint32_t y; - uint32_t z; -} VkDispatchIndirectCommand; - -typedef struct VkDrawIndexedIndirectCommand { - uint32_t indexCount; - uint32_t instanceCount; - uint32_t firstIndex; - int32_t vertexOffset; - uint32_t firstInstance; -} VkDrawIndexedIndirectCommand; - -typedef struct VkDrawIndirectCommand { - uint32_t vertexCount; - uint32_t instanceCount; - uint32_t firstVertex; - uint32_t firstInstance; -} VkDrawIndirectCommand; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateInstance)(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance); -typedef void (VKAPI_PTR *PFN_vkDestroyInstance)(VkInstance instance, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDevices)(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties); -typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetInstanceProcAddr)(VkInstance instance, const char* pName); -typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetDeviceProcAddr)(VkDevice device, const char* pName); -typedef VkResult (VKAPI_PTR *PFN_vkCreateDevice)(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice); -typedef void (VKAPI_PTR *PFN_vkDestroyDevice)(VkDevice device, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceExtensionProperties)(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceExtensionProperties)(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceLayerProperties)(uint32_t* pPropertyCount, VkLayerProperties* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceLayerProperties)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties); -typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue)(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue); -typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence); -typedef VkResult (VKAPI_PTR *PFN_vkQueueWaitIdle)(VkQueue queue); -typedef VkResult (VKAPI_PTR *PFN_vkDeviceWaitIdle)(VkDevice device); -typedef VkResult (VKAPI_PTR *PFN_vkAllocateMemory)(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory); -typedef void (VKAPI_PTR *PFN_vkFreeMemory)(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkMapMemory)(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData); -typedef void (VKAPI_PTR *PFN_vkUnmapMemory)(VkDevice device, VkDeviceMemory memory); -typedef VkResult (VKAPI_PTR *PFN_vkFlushMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges); -typedef VkResult (VKAPI_PTR *PFN_vkInvalidateMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges); -typedef void (VKAPI_PTR *PFN_vkGetDeviceMemoryCommitment)(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes); -typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory)(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset); -typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory)(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset); -typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements)(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements); -typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements)(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements); -typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements)(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkQueueBindSparse)(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence); -typedef VkResult (VKAPI_PTR *PFN_vkCreateFence)(VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); -typedef void (VKAPI_PTR *PFN_vkDestroyFence)(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkResetFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences); -typedef VkResult (VKAPI_PTR *PFN_vkGetFenceStatus)(VkDevice device, VkFence fence); -typedef VkResult (VKAPI_PTR *PFN_vkWaitForFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout); -typedef VkResult (VKAPI_PTR *PFN_vkCreateSemaphore)(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore); -typedef void (VKAPI_PTR *PFN_vkDestroySemaphore)(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateEvent)(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent); -typedef void (VKAPI_PTR *PFN_vkDestroyEvent)(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkGetEventStatus)(VkDevice device, VkEvent event); -typedef VkResult (VKAPI_PTR *PFN_vkSetEvent)(VkDevice device, VkEvent event); -typedef VkResult (VKAPI_PTR *PFN_vkResetEvent)(VkDevice device, VkEvent event); -typedef VkResult (VKAPI_PTR *PFN_vkCreateQueryPool)(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool); -typedef void (VKAPI_PTR *PFN_vkDestroyQueryPool)(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkGetQueryPoolResults)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags); -typedef VkResult (VKAPI_PTR *PFN_vkCreateBuffer)(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer); -typedef void (VKAPI_PTR *PFN_vkDestroyBuffer)(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView); -typedef void (VKAPI_PTR *PFN_vkDestroyBufferView)(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateImage)(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage); -typedef void (VKAPI_PTR *PFN_vkDestroyImage)(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout)(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout); -typedef VkResult (VKAPI_PTR *PFN_vkCreateImageView)(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView); -typedef void (VKAPI_PTR *PFN_vkDestroyImageView)(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateShaderModule)(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule); -typedef void (VKAPI_PTR *PFN_vkDestroyShaderModule)(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineCache)(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache); -typedef void (VKAPI_PTR *PFN_vkDestroyPipelineCache)(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineCacheData)(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData); -typedef VkResult (VKAPI_PTR *PFN_vkMergePipelineCaches)(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches); -typedef VkResult (VKAPI_PTR *PFN_vkCreateGraphicsPipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); -typedef VkResult (VKAPI_PTR *PFN_vkCreateComputePipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); -typedef void (VKAPI_PTR *PFN_vkDestroyPipeline)(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineLayout)(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout); -typedef void (VKAPI_PTR *PFN_vkDestroyPipelineLayout)(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateSampler)(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler); -typedef void (VKAPI_PTR *PFN_vkDestroySampler)(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorSetLayout)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout); -typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorSetLayout)(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorPool)(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool); -typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkResetDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags); -typedef VkResult (VKAPI_PTR *PFN_vkAllocateDescriptorSets)(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets); -typedef VkResult (VKAPI_PTR *PFN_vkFreeDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets); -typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSets)(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies); -typedef VkResult (VKAPI_PTR *PFN_vkCreateFramebuffer)(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer); -typedef void (VKAPI_PTR *PFN_vkDestroyFramebuffer)(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass)(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); -typedef void (VKAPI_PTR *PFN_vkDestroyRenderPass)(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkGetRenderAreaGranularity)(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity); -typedef VkResult (VKAPI_PTR *PFN_vkCreateCommandPool)(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool); -typedef void (VKAPI_PTR *PFN_vkDestroyCommandPool)(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkResetCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags); -typedef VkResult (VKAPI_PTR *PFN_vkAllocateCommandBuffers)(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers); -typedef void (VKAPI_PTR *PFN_vkFreeCommandBuffers)(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); -typedef VkResult (VKAPI_PTR *PFN_vkBeginCommandBuffer)(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo); -typedef VkResult (VKAPI_PTR *PFN_vkEndCommandBuffer)(VkCommandBuffer commandBuffer); -typedef VkResult (VKAPI_PTR *PFN_vkResetCommandBuffer)(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags); -typedef void (VKAPI_PTR *PFN_vkCmdBindPipeline)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline); -typedef void (VKAPI_PTR *PFN_vkCmdSetViewport)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports); -typedef void (VKAPI_PTR *PFN_vkCmdSetScissor)(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors); -typedef void (VKAPI_PTR *PFN_vkCmdSetLineWidth)(VkCommandBuffer commandBuffer, float lineWidth); -typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBias)(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor); -typedef void (VKAPI_PTR *PFN_vkCmdSetBlendConstants)(VkCommandBuffer commandBuffer, const float blendConstants[4]); -typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBounds)(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds); -typedef void (VKAPI_PTR *PFN_vkCmdSetStencilCompareMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask); -typedef void (VKAPI_PTR *PFN_vkCmdSetStencilWriteMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask); -typedef void (VKAPI_PTR *PFN_vkCmdSetStencilReference)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference); -typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets); -typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType); -typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets); -typedef void (VKAPI_PTR *PFN_vkCmdDraw)(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance); -typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexed)(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance); -typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); -typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); -typedef void (VKAPI_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); -typedef void (VKAPI_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset); -typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions); -typedef void (VKAPI_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions); -typedef void (VKAPI_PTR *PFN_vkCmdBlitImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter); -typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions); -typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions); -typedef void (VKAPI_PTR *PFN_vkCmdUpdateBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData); -typedef void (VKAPI_PTR *PFN_vkCmdFillBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data); -typedef void (VKAPI_PTR *PFN_vkCmdClearColorImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges); -typedef void (VKAPI_PTR *PFN_vkCmdClearDepthStencilImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges); -typedef void (VKAPI_PTR *PFN_vkCmdClearAttachments)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects); -typedef void (VKAPI_PTR *PFN_vkCmdResolveImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions); -typedef void (VKAPI_PTR *PFN_vkCmdSetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); -typedef void (VKAPI_PTR *PFN_vkCmdResetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); -typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); -typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier)(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); -typedef void (VKAPI_PTR *PFN_vkCmdBeginQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags); -typedef void (VKAPI_PTR *PFN_vkCmdEndQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query); -typedef void (VKAPI_PTR *PFN_vkCmdResetQueryPool)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); -typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query); -typedef void (VKAPI_PTR *PFN_vkCmdCopyQueryPoolResults)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags); -typedef void (VKAPI_PTR *PFN_vkCmdPushConstants)(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues); -typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents); -typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass)(VkCommandBuffer commandBuffer, VkSubpassContents contents); -typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass)(VkCommandBuffer commandBuffer); -typedef void (VKAPI_PTR *PFN_vkCmdExecuteCommands)(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance( - const VkInstanceCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkInstance* pInstance); - -VKAPI_ATTR void VKAPI_CALL vkDestroyInstance( - VkInstance instance, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices( - VkInstance instance, - uint32_t* pPhysicalDeviceCount, - VkPhysicalDevice* pPhysicalDevices); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures( - VkPhysicalDevice physicalDevice, - VkPhysicalDeviceFeatures* pFeatures); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties( - VkPhysicalDevice physicalDevice, - VkFormat format, - VkFormatProperties* pFormatProperties); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties( - VkPhysicalDevice physicalDevice, - VkFormat format, - VkImageType type, - VkImageTiling tiling, - VkImageUsageFlags usage, - VkImageCreateFlags flags, - VkImageFormatProperties* pImageFormatProperties); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties( - VkPhysicalDevice physicalDevice, - VkPhysicalDeviceProperties* pProperties); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties( - VkPhysicalDevice physicalDevice, - uint32_t* pQueueFamilyPropertyCount, - VkQueueFamilyProperties* pQueueFamilyProperties); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties( - VkPhysicalDevice physicalDevice, - VkPhysicalDeviceMemoryProperties* pMemoryProperties); - -VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr( - VkInstance instance, - const char* pName); - -VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr( - VkDevice device, - const char* pName); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice( - VkPhysicalDevice physicalDevice, - const VkDeviceCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDevice* pDevice); - -VKAPI_ATTR void VKAPI_CALL vkDestroyDevice( - VkDevice device, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties( - const char* pLayerName, - uint32_t* pPropertyCount, - VkExtensionProperties* pProperties); - -VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties( - VkPhysicalDevice physicalDevice, - const char* pLayerName, - uint32_t* pPropertyCount, - VkExtensionProperties* pProperties); - -VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties( - uint32_t* pPropertyCount, - VkLayerProperties* pProperties); - -VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties( - VkPhysicalDevice physicalDevice, - uint32_t* pPropertyCount, - VkLayerProperties* pProperties); - -VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue( - VkDevice device, - uint32_t queueFamilyIndex, - uint32_t queueIndex, - VkQueue* pQueue); - -VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit( - VkQueue queue, - uint32_t submitCount, - const VkSubmitInfo* pSubmits, - VkFence fence); - -VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle( - VkQueue queue); - -VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle( - VkDevice device); - -VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory( - VkDevice device, - const VkMemoryAllocateInfo* pAllocateInfo, - const VkAllocationCallbacks* pAllocator, - VkDeviceMemory* pMemory); - -VKAPI_ATTR void VKAPI_CALL vkFreeMemory( - VkDevice device, - VkDeviceMemory memory, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory( - VkDevice device, - VkDeviceMemory memory, - VkDeviceSize offset, - VkDeviceSize size, - VkMemoryMapFlags flags, - void** ppData); - -VKAPI_ATTR void VKAPI_CALL vkUnmapMemory( - VkDevice device, - VkDeviceMemory memory); - -VKAPI_ATTR VkResult VKAPI_CALL vkFlushMappedMemoryRanges( - VkDevice device, - uint32_t memoryRangeCount, - const VkMappedMemoryRange* pMemoryRanges); - -VKAPI_ATTR VkResult VKAPI_CALL vkInvalidateMappedMemoryRanges( - VkDevice device, - uint32_t memoryRangeCount, - const VkMappedMemoryRange* pMemoryRanges); - -VKAPI_ATTR void VKAPI_CALL vkGetDeviceMemoryCommitment( - VkDevice device, - VkDeviceMemory memory, - VkDeviceSize* pCommittedMemoryInBytes); - -VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory( - VkDevice device, - VkBuffer buffer, - VkDeviceMemory memory, - VkDeviceSize memoryOffset); - -VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory( - VkDevice device, - VkImage image, - VkDeviceMemory memory, - VkDeviceSize memoryOffset); - -VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements( - VkDevice device, - VkBuffer buffer, - VkMemoryRequirements* pMemoryRequirements); - -VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements( - VkDevice device, - VkImage image, - VkMemoryRequirements* pMemoryRequirements); - -VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements( - VkDevice device, - VkImage image, - uint32_t* pSparseMemoryRequirementCount, - VkSparseImageMemoryRequirements* pSparseMemoryRequirements); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties( - VkPhysicalDevice physicalDevice, - VkFormat format, - VkImageType type, - VkSampleCountFlagBits samples, - VkImageUsageFlags usage, - VkImageTiling tiling, - uint32_t* pPropertyCount, - VkSparseImageFormatProperties* pProperties); - -VKAPI_ATTR VkResult VKAPI_CALL vkQueueBindSparse( - VkQueue queue, - uint32_t bindInfoCount, - const VkBindSparseInfo* pBindInfo, - VkFence fence); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateFence( - VkDevice device, - const VkFenceCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkFence* pFence); - -VKAPI_ATTR void VKAPI_CALL vkDestroyFence( - VkDevice device, - VkFence fence, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkResetFences( - VkDevice device, - uint32_t fenceCount, - const VkFence* pFences); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus( - VkDevice device, - VkFence fence); - -VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences( - VkDevice device, - uint32_t fenceCount, - const VkFence* pFences, - VkBool32 waitAll, - uint64_t timeout); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore( - VkDevice device, - const VkSemaphoreCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSemaphore* pSemaphore); - -VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore( - VkDevice device, - VkSemaphore semaphore, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent( - VkDevice device, - const VkEventCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkEvent* pEvent); - -VKAPI_ATTR void VKAPI_CALL vkDestroyEvent( - VkDevice device, - VkEvent event, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus( - VkDevice device, - VkEvent event); - -VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent( - VkDevice device, - VkEvent event); - -VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent( - VkDevice device, - VkEvent event); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateQueryPool( - VkDevice device, - const VkQueryPoolCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkQueryPool* pQueryPool); - -VKAPI_ATTR void VKAPI_CALL vkDestroyQueryPool( - VkDevice device, - VkQueryPool queryPool, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults( - VkDevice device, - VkQueryPool queryPool, - uint32_t firstQuery, - uint32_t queryCount, - size_t dataSize, - void* pData, - VkDeviceSize stride, - VkQueryResultFlags flags); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateBuffer( - VkDevice device, - const VkBufferCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkBuffer* pBuffer); - -VKAPI_ATTR void VKAPI_CALL vkDestroyBuffer( - VkDevice device, - VkBuffer buffer, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView( - VkDevice device, - const VkBufferViewCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkBufferView* pView); - -VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView( - VkDevice device, - VkBufferView bufferView, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage( - VkDevice device, - const VkImageCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkImage* pImage); - -VKAPI_ATTR void VKAPI_CALL vkDestroyImage( - VkDevice device, - VkImage image, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout( - VkDevice device, - VkImage image, - const VkImageSubresource* pSubresource, - VkSubresourceLayout* pLayout); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView( - VkDevice device, - const VkImageViewCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkImageView* pView); - -VKAPI_ATTR void VKAPI_CALL vkDestroyImageView( - VkDevice device, - VkImageView imageView, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule( - VkDevice device, - const VkShaderModuleCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkShaderModule* pShaderModule); - -VKAPI_ATTR void VKAPI_CALL vkDestroyShaderModule( - VkDevice device, - VkShaderModule shaderModule, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache( - VkDevice device, - const VkPipelineCacheCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkPipelineCache* pPipelineCache); - -VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineCache( - VkDevice device, - VkPipelineCache pipelineCache, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineCacheData( - VkDevice device, - VkPipelineCache pipelineCache, - size_t* pDataSize, - void* pData); - -VKAPI_ATTR VkResult VKAPI_CALL vkMergePipelineCaches( - VkDevice device, - VkPipelineCache dstCache, - uint32_t srcCacheCount, - const VkPipelineCache* pSrcCaches); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines( - VkDevice device, - VkPipelineCache pipelineCache, - uint32_t createInfoCount, - const VkGraphicsPipelineCreateInfo* pCreateInfos, - const VkAllocationCallbacks* pAllocator, - VkPipeline* pPipelines); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateComputePipelines( - VkDevice device, - VkPipelineCache pipelineCache, - uint32_t createInfoCount, - const VkComputePipelineCreateInfo* pCreateInfos, - const VkAllocationCallbacks* pAllocator, - VkPipeline* pPipelines); - -VKAPI_ATTR void VKAPI_CALL vkDestroyPipeline( - VkDevice device, - VkPipeline pipeline, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineLayout( - VkDevice device, - const VkPipelineLayoutCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkPipelineLayout* pPipelineLayout); - -VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineLayout( - VkDevice device, - VkPipelineLayout pipelineLayout, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler( - VkDevice device, - const VkSamplerCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSampler* pSampler); - -VKAPI_ATTR void VKAPI_CALL vkDestroySampler( - VkDevice device, - VkSampler sampler, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorSetLayout( - VkDevice device, - const VkDescriptorSetLayoutCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDescriptorSetLayout* pSetLayout); - -VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorSetLayout( - VkDevice device, - VkDescriptorSetLayout descriptorSetLayout, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorPool( - VkDevice device, - const VkDescriptorPoolCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDescriptorPool* pDescriptorPool); - -VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorPool( - VkDevice device, - VkDescriptorPool descriptorPool, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkResetDescriptorPool( - VkDevice device, - VkDescriptorPool descriptorPool, - VkDescriptorPoolResetFlags flags); - -VKAPI_ATTR VkResult VKAPI_CALL vkAllocateDescriptorSets( - VkDevice device, - const VkDescriptorSetAllocateInfo* pAllocateInfo, - VkDescriptorSet* pDescriptorSets); - -VKAPI_ATTR VkResult VKAPI_CALL vkFreeDescriptorSets( - VkDevice device, - VkDescriptorPool descriptorPool, - uint32_t descriptorSetCount, - const VkDescriptorSet* pDescriptorSets); - -VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSets( - VkDevice device, - uint32_t descriptorWriteCount, - const VkWriteDescriptorSet* pDescriptorWrites, - uint32_t descriptorCopyCount, - const VkCopyDescriptorSet* pDescriptorCopies); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer( - VkDevice device, - const VkFramebufferCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkFramebuffer* pFramebuffer); - -VKAPI_ATTR void VKAPI_CALL vkDestroyFramebuffer( - VkDevice device, - VkFramebuffer framebuffer, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass( - VkDevice device, - const VkRenderPassCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkRenderPass* pRenderPass); - -VKAPI_ATTR void VKAPI_CALL vkDestroyRenderPass( - VkDevice device, - VkRenderPass renderPass, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR void VKAPI_CALL vkGetRenderAreaGranularity( - VkDevice device, - VkRenderPass renderPass, - VkExtent2D* pGranularity); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool( - VkDevice device, - const VkCommandPoolCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkCommandPool* pCommandPool); - -VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool( - VkDevice device, - VkCommandPool commandPool, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandPool( - VkDevice device, - VkCommandPool commandPool, - VkCommandPoolResetFlags flags); - -VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers( - VkDevice device, - const VkCommandBufferAllocateInfo* pAllocateInfo, - VkCommandBuffer* pCommandBuffers); - -VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers( - VkDevice device, - VkCommandPool commandPool, - uint32_t commandBufferCount, - const VkCommandBuffer* pCommandBuffers); - -VKAPI_ATTR VkResult VKAPI_CALL vkBeginCommandBuffer( - VkCommandBuffer commandBuffer, - const VkCommandBufferBeginInfo* pBeginInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer( - VkCommandBuffer commandBuffer); - -VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer( - VkCommandBuffer commandBuffer, - VkCommandBufferResetFlags flags); - -VKAPI_ATTR void VKAPI_CALL vkCmdBindPipeline( - VkCommandBuffer commandBuffer, - VkPipelineBindPoint pipelineBindPoint, - VkPipeline pipeline); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetViewport( - VkCommandBuffer commandBuffer, - uint32_t firstViewport, - uint32_t viewportCount, - const VkViewport* pViewports); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetScissor( - VkCommandBuffer commandBuffer, - uint32_t firstScissor, - uint32_t scissorCount, - const VkRect2D* pScissors); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetLineWidth( - VkCommandBuffer commandBuffer, - float lineWidth); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias( - VkCommandBuffer commandBuffer, - float depthBiasConstantFactor, - float depthBiasClamp, - float depthBiasSlopeFactor); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants( - VkCommandBuffer commandBuffer, - const float blendConstants[4]); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBounds( - VkCommandBuffer commandBuffer, - float minDepthBounds, - float maxDepthBounds); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilCompareMask( - VkCommandBuffer commandBuffer, - VkStencilFaceFlags faceMask, - uint32_t compareMask); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilWriteMask( - VkCommandBuffer commandBuffer, - VkStencilFaceFlags faceMask, - uint32_t writeMask); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilReference( - VkCommandBuffer commandBuffer, - VkStencilFaceFlags faceMask, - uint32_t reference); - -VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets( - VkCommandBuffer commandBuffer, - VkPipelineBindPoint pipelineBindPoint, - VkPipelineLayout layout, - uint32_t firstSet, - uint32_t descriptorSetCount, - const VkDescriptorSet* pDescriptorSets, - uint32_t dynamicOffsetCount, - const uint32_t* pDynamicOffsets); - -VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer( - VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - VkIndexType indexType); - -VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers( - VkCommandBuffer commandBuffer, - uint32_t firstBinding, - uint32_t bindingCount, - const VkBuffer* pBuffers, - const VkDeviceSize* pOffsets); - -VKAPI_ATTR void VKAPI_CALL vkCmdDraw( - VkCommandBuffer commandBuffer, - uint32_t vertexCount, - uint32_t instanceCount, - uint32_t firstVertex, - uint32_t firstInstance); - -VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexed( - VkCommandBuffer commandBuffer, - uint32_t indexCount, - uint32_t instanceCount, - uint32_t firstIndex, - int32_t vertexOffset, - uint32_t firstInstance); - -VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirect( - VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - uint32_t drawCount, - uint32_t stride); - -VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect( - VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - uint32_t drawCount, - uint32_t stride); - -VKAPI_ATTR void VKAPI_CALL vkCmdDispatch( - VkCommandBuffer commandBuffer, - uint32_t groupCountX, - uint32_t groupCountY, - uint32_t groupCountZ); - -VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect( - VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset); - -VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer( - VkCommandBuffer commandBuffer, - VkBuffer srcBuffer, - VkBuffer dstBuffer, - uint32_t regionCount, - const VkBufferCopy* pRegions); - -VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage( - VkCommandBuffer commandBuffer, - VkImage srcImage, - VkImageLayout srcImageLayout, - VkImage dstImage, - VkImageLayout dstImageLayout, - uint32_t regionCount, - const VkImageCopy* pRegions); - -VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage( - VkCommandBuffer commandBuffer, - VkImage srcImage, - VkImageLayout srcImageLayout, - VkImage dstImage, - VkImageLayout dstImageLayout, - uint32_t regionCount, - const VkImageBlit* pRegions, - VkFilter filter); - -VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage( - VkCommandBuffer commandBuffer, - VkBuffer srcBuffer, - VkImage dstImage, - VkImageLayout dstImageLayout, - uint32_t regionCount, - const VkBufferImageCopy* pRegions); - -VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer( - VkCommandBuffer commandBuffer, - VkImage srcImage, - VkImageLayout srcImageLayout, - VkBuffer dstBuffer, - uint32_t regionCount, - const VkBufferImageCopy* pRegions); - -VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer( - VkCommandBuffer commandBuffer, - VkBuffer dstBuffer, - VkDeviceSize dstOffset, - VkDeviceSize dataSize, - const void* pData); - -VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer( - VkCommandBuffer commandBuffer, - VkBuffer dstBuffer, - VkDeviceSize dstOffset, - VkDeviceSize size, - uint32_t data); - -VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage( - VkCommandBuffer commandBuffer, - VkImage image, - VkImageLayout imageLayout, - const VkClearColorValue* pColor, - uint32_t rangeCount, - const VkImageSubresourceRange* pRanges); - -VKAPI_ATTR void VKAPI_CALL vkCmdClearDepthStencilImage( - VkCommandBuffer commandBuffer, - VkImage image, - VkImageLayout imageLayout, - const VkClearDepthStencilValue* pDepthStencil, - uint32_t rangeCount, - const VkImageSubresourceRange* pRanges); - -VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments( - VkCommandBuffer commandBuffer, - uint32_t attachmentCount, - const VkClearAttachment* pAttachments, - uint32_t rectCount, - const VkClearRect* pRects); - -VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage( - VkCommandBuffer commandBuffer, - VkImage srcImage, - VkImageLayout srcImageLayout, - VkImage dstImage, - VkImageLayout dstImageLayout, - uint32_t regionCount, - const VkImageResolve* pRegions); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent( - VkCommandBuffer commandBuffer, - VkEvent event, - VkPipelineStageFlags stageMask); - -VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent( - VkCommandBuffer commandBuffer, - VkEvent event, - VkPipelineStageFlags stageMask); - -VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents( - VkCommandBuffer commandBuffer, - uint32_t eventCount, - const VkEvent* pEvents, - VkPipelineStageFlags srcStageMask, - VkPipelineStageFlags dstStageMask, - uint32_t memoryBarrierCount, - const VkMemoryBarrier* pMemoryBarriers, - uint32_t bufferMemoryBarrierCount, - const VkBufferMemoryBarrier* pBufferMemoryBarriers, - uint32_t imageMemoryBarrierCount, - const VkImageMemoryBarrier* pImageMemoryBarriers); - -VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier( - VkCommandBuffer commandBuffer, - VkPipelineStageFlags srcStageMask, - VkPipelineStageFlags dstStageMask, - VkDependencyFlags dependencyFlags, - uint32_t memoryBarrierCount, - const VkMemoryBarrier* pMemoryBarriers, - uint32_t bufferMemoryBarrierCount, - const VkBufferMemoryBarrier* pBufferMemoryBarriers, - uint32_t imageMemoryBarrierCount, - const VkImageMemoryBarrier* pImageMemoryBarriers); - -VKAPI_ATTR void VKAPI_CALL vkCmdBeginQuery( - VkCommandBuffer commandBuffer, - VkQueryPool queryPool, - uint32_t query, - VkQueryControlFlags flags); - -VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery( - VkCommandBuffer commandBuffer, - VkQueryPool queryPool, - uint32_t query); - -VKAPI_ATTR void VKAPI_CALL vkCmdResetQueryPool( - VkCommandBuffer commandBuffer, - VkQueryPool queryPool, - uint32_t firstQuery, - uint32_t queryCount); - -VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp( - VkCommandBuffer commandBuffer, - VkPipelineStageFlagBits pipelineStage, - VkQueryPool queryPool, - uint32_t query); - -VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResults( - VkCommandBuffer commandBuffer, - VkQueryPool queryPool, - uint32_t firstQuery, - uint32_t queryCount, - VkBuffer dstBuffer, - VkDeviceSize dstOffset, - VkDeviceSize stride, - VkQueryResultFlags flags); - -VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants( - VkCommandBuffer commandBuffer, - VkPipelineLayout layout, - VkShaderStageFlags stageFlags, - uint32_t offset, - uint32_t size, - const void* pValues); - -VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass( - VkCommandBuffer commandBuffer, - const VkRenderPassBeginInfo* pRenderPassBegin, - VkSubpassContents contents); - -VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass( - VkCommandBuffer commandBuffer, - VkSubpassContents contents); - -VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass( - VkCommandBuffer commandBuffer); - -VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands( - VkCommandBuffer commandBuffer, - uint32_t commandBufferCount, - const VkCommandBuffer* pCommandBuffers); -#endif - -#define VK_KHR_surface 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) - -#define VK_KHR_SURFACE_SPEC_VERSION 25 -#define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface" -#define VK_COLORSPACE_SRGB_NONLINEAR_KHR VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - - -typedef enum VkColorSpaceKHR { - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0, - VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001, - VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002, - VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104003, - VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004, - VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005, - VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006, - VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007, - VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008, - VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009, - VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010, - VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011, - VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012, - VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013, - VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014, - VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, - VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, - VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1), - VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkColorSpaceKHR; - -typedef enum VkPresentModeKHR { - VK_PRESENT_MODE_IMMEDIATE_KHR = 0, - VK_PRESENT_MODE_MAILBOX_KHR = 1, - VK_PRESENT_MODE_FIFO_KHR = 2, - VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, - VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000, - VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001, - VK_PRESENT_MODE_BEGIN_RANGE_KHR = VK_PRESENT_MODE_IMMEDIATE_KHR, - VK_PRESENT_MODE_END_RANGE_KHR = VK_PRESENT_MODE_FIFO_RELAXED_KHR, - VK_PRESENT_MODE_RANGE_SIZE_KHR = (VK_PRESENT_MODE_FIFO_RELAXED_KHR - VK_PRESENT_MODE_IMMEDIATE_KHR + 1), - VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkPresentModeKHR; - - -typedef enum VkSurfaceTransformFlagBitsKHR { - VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001, - VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002, - VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0x00000004, - VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0x00000008, - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0x00000010, - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0x00000020, - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040, - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080, - VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100, - VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkSurfaceTransformFlagBitsKHR; -typedef VkFlags VkSurfaceTransformFlagsKHR; - -typedef enum VkCompositeAlphaFlagBitsKHR { - VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, - VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002, - VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004, - VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008, - VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkCompositeAlphaFlagBitsKHR; -typedef VkFlags VkCompositeAlphaFlagsKHR; - -typedef struct VkSurfaceCapabilitiesKHR { - uint32_t minImageCount; - uint32_t maxImageCount; - VkExtent2D currentExtent; - VkExtent2D minImageExtent; - VkExtent2D maxImageExtent; - uint32_t maxImageArrayLayers; - VkSurfaceTransformFlagsKHR supportedTransforms; - VkSurfaceTransformFlagBitsKHR currentTransform; - VkCompositeAlphaFlagsKHR supportedCompositeAlpha; - VkImageUsageFlags supportedUsageFlags; -} VkSurfaceCapabilitiesKHR; - -typedef struct VkSurfaceFormatKHR { - VkFormat format; - VkColorSpaceKHR colorSpace; -} VkSurfaceFormatKHR; - - -typedef void (VKAPI_PTR *PFN_vkDestroySurfaceKHR)(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR( - VkInstance instance, - VkSurfaceKHR surface, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - VkSurfaceKHR surface, - VkBool32* pSupported); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR( - VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR( - VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - uint32_t* pSurfaceFormatCount, - VkSurfaceFormatKHR* pSurfaceFormats); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR( - VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - uint32_t* pPresentModeCount, - VkPresentModeKHR* pPresentModes); -#endif - -#define VK_KHR_swapchain 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR) - -#define VK_KHR_SWAPCHAIN_SPEC_VERSION 68 -#define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain" - - -typedef enum VkSwapchainCreateFlagBitsKHR { - VK_SWAPCHAIN_CREATE_BIND_SFR_BIT_KHX = 0x00000001, - VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkSwapchainCreateFlagBitsKHR; -typedef VkFlags VkSwapchainCreateFlagsKHR; - -typedef struct VkSwapchainCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkSwapchainCreateFlagsKHR flags; - VkSurfaceKHR surface; - uint32_t minImageCount; - VkFormat imageFormat; - VkColorSpaceKHR imageColorSpace; - VkExtent2D imageExtent; - uint32_t imageArrayLayers; - VkImageUsageFlags imageUsage; - VkSharingMode imageSharingMode; - uint32_t queueFamilyIndexCount; - const uint32_t* pQueueFamilyIndices; - VkSurfaceTransformFlagBitsKHR preTransform; - VkCompositeAlphaFlagBitsKHR compositeAlpha; - VkPresentModeKHR presentMode; - VkBool32 clipped; - VkSwapchainKHR oldSwapchain; -} VkSwapchainCreateInfoKHR; - -typedef struct VkPresentInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t waitSemaphoreCount; - const VkSemaphore* pWaitSemaphores; - uint32_t swapchainCount; - const VkSwapchainKHR* pSwapchains; - const uint32_t* pImageIndices; - VkResult* pResults; -} VkPresentInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateSwapchainKHR)(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain); -typedef void (VKAPI_PTR *PFN_vkDestroySwapchainKHR)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages); -typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImageKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex); -typedef VkResult (VKAPI_PTR *PFN_vkQueuePresentKHR)(VkQueue queue, const VkPresentInfoKHR* pPresentInfo); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR( - VkDevice device, - const VkSwapchainCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSwapchainKHR* pSwapchain); - -VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR( - VkDevice device, - VkSwapchainKHR swapchain, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR( - VkDevice device, - VkSwapchainKHR swapchain, - uint32_t* pSwapchainImageCount, - VkImage* pSwapchainImages); - -VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR( - VkDevice device, - VkSwapchainKHR swapchain, - uint64_t timeout, - VkSemaphore semaphore, - VkFence fence, - uint32_t* pImageIndex); - -VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR( - VkQueue queue, - const VkPresentInfoKHR* pPresentInfo); -#endif - -#define VK_KHR_display 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayModeKHR) - -#define VK_KHR_DISPLAY_SPEC_VERSION 21 -#define VK_KHR_DISPLAY_EXTENSION_NAME "VK_KHR_display" - - -typedef enum VkDisplayPlaneAlphaFlagBitsKHR { - VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, - VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002, - VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0x00000004, - VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008, - VK_DISPLAY_PLANE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkDisplayPlaneAlphaFlagBitsKHR; -typedef VkFlags VkDisplayPlaneAlphaFlagsKHR; -typedef VkFlags VkDisplayModeCreateFlagsKHR; -typedef VkFlags VkDisplaySurfaceCreateFlagsKHR; - -typedef struct VkDisplayPropertiesKHR { - VkDisplayKHR display; - const char* displayName; - VkExtent2D physicalDimensions; - VkExtent2D physicalResolution; - VkSurfaceTransformFlagsKHR supportedTransforms; - VkBool32 planeReorderPossible; - VkBool32 persistentContent; -} VkDisplayPropertiesKHR; - -typedef struct VkDisplayModeParametersKHR { - VkExtent2D visibleRegion; - uint32_t refreshRate; -} VkDisplayModeParametersKHR; - -typedef struct VkDisplayModePropertiesKHR { - VkDisplayModeKHR displayMode; - VkDisplayModeParametersKHR parameters; -} VkDisplayModePropertiesKHR; - -typedef struct VkDisplayModeCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkDisplayModeCreateFlagsKHR flags; - VkDisplayModeParametersKHR parameters; -} VkDisplayModeCreateInfoKHR; - -typedef struct VkDisplayPlaneCapabilitiesKHR { - VkDisplayPlaneAlphaFlagsKHR supportedAlpha; - VkOffset2D minSrcPosition; - VkOffset2D maxSrcPosition; - VkExtent2D minSrcExtent; - VkExtent2D maxSrcExtent; - VkOffset2D minDstPosition; - VkOffset2D maxDstPosition; - VkExtent2D minDstExtent; - VkExtent2D maxDstExtent; -} VkDisplayPlaneCapabilitiesKHR; - -typedef struct VkDisplayPlanePropertiesKHR { - VkDisplayKHR currentDisplay; - uint32_t currentStackIndex; -} VkDisplayPlanePropertiesKHR; - -typedef struct VkDisplaySurfaceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkDisplaySurfaceCreateFlagsKHR flags; - VkDisplayModeKHR displayMode; - uint32_t planeIndex; - uint32_t planeStackIndex; - VkSurfaceTransformFlagBitsKHR transform; - float globalAlpha; - VkDisplayPlaneAlphaFlagBitsKHR alphaMode; - VkExtent2D imageExtent; -} VkDisplaySurfaceCreateInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneSupportedDisplaysKHR)(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays); -typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModePropertiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayModeKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode); -typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities); -typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayPlaneSurfaceKHR)(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR( - VkPhysicalDevice physicalDevice, - uint32_t* pPropertyCount, - VkDisplayPropertiesKHR* pProperties); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlanePropertiesKHR( - VkPhysicalDevice physicalDevice, - uint32_t* pPropertyCount, - VkDisplayPlanePropertiesKHR* pProperties); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneSupportedDisplaysKHR( - VkPhysicalDevice physicalDevice, - uint32_t planeIndex, - uint32_t* pDisplayCount, - VkDisplayKHR* pDisplays); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR( - VkPhysicalDevice physicalDevice, - VkDisplayKHR display, - uint32_t* pPropertyCount, - VkDisplayModePropertiesKHR* pProperties); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR( - VkPhysicalDevice physicalDevice, - VkDisplayKHR display, - const VkDisplayModeCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDisplayModeKHR* pMode); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR( - VkPhysicalDevice physicalDevice, - VkDisplayModeKHR mode, - uint32_t planeIndex, - VkDisplayPlaneCapabilitiesKHR* pCapabilities); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR( - VkInstance instance, - const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); -#endif - -#define VK_KHR_display_swapchain 1 -#define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION 9 -#define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME "VK_KHR_display_swapchain" - -typedef struct VkDisplayPresentInfoKHR { - VkStructureType sType; - const void* pNext; - VkRect2D srcRect; - VkRect2D dstRect; - VkBool32 persistent; -} VkDisplayPresentInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateSharedSwapchainsKHR)(VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( - VkDevice device, - uint32_t swapchainCount, - const VkSwapchainCreateInfoKHR* pCreateInfos, - const VkAllocationCallbacks* pAllocator, - VkSwapchainKHR* pSwapchains); -#endif - -#ifdef VK_USE_PLATFORM_XLIB_KHR -#define VK_KHR_xlib_surface 1 -#include - -#define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6 -#define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface" - -typedef VkFlags VkXlibSurfaceCreateFlagsKHR; - -typedef struct VkXlibSurfaceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkXlibSurfaceCreateFlagsKHR flags; - Display* dpy; - Window window; -} VkXlibSurfaceCreateInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateXlibSurfaceKHR)(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); -typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR( - VkInstance instance, - const VkXlibSurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); - -VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - Display* dpy, - VisualID visualID); -#endif -#endif /* VK_USE_PLATFORM_XLIB_KHR */ - -#ifdef VK_USE_PLATFORM_XCB_KHR -#define VK_KHR_xcb_surface 1 -#include - -#define VK_KHR_XCB_SURFACE_SPEC_VERSION 6 -#define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface" - -typedef VkFlags VkXcbSurfaceCreateFlagsKHR; - -typedef struct VkXcbSurfaceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkXcbSurfaceCreateFlagsKHR flags; - xcb_connection_t* connection; - xcb_window_t window; -} VkXcbSurfaceCreateInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateXcbSurfaceKHR)(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); -typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR( - VkInstance instance, - const VkXcbSurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); - -VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - xcb_connection_t* connection, - xcb_visualid_t visual_id); -#endif -#endif /* VK_USE_PLATFORM_XCB_KHR */ - -#ifdef VK_USE_PLATFORM_WAYLAND_KHR -#define VK_KHR_wayland_surface 1 -#include - -#define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6 -#define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface" - -typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; - -typedef struct VkWaylandSurfaceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkWaylandSurfaceCreateFlagsKHR flags; - struct wl_display* display; - struct wl_surface* surface; -} VkWaylandSurfaceCreateInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateWaylandSurfaceKHR)(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); -typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct wl_display* display); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR( - VkInstance instance, - const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); - -VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - struct wl_display* display); -#endif -#endif /* VK_USE_PLATFORM_WAYLAND_KHR */ - -#ifdef VK_USE_PLATFORM_MIR_KHR -#define VK_KHR_mir_surface 1 -#include - -#define VK_KHR_MIR_SURFACE_SPEC_VERSION 4 -#define VK_KHR_MIR_SURFACE_EXTENSION_NAME "VK_KHR_mir_surface" - -typedef VkFlags VkMirSurfaceCreateFlagsKHR; - -typedef struct VkMirSurfaceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkMirSurfaceCreateFlagsKHR flags; - MirConnection* connection; - MirSurface* mirSurface; -} VkMirSurfaceCreateInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateMirSurfaceKHR)(VkInstance instance, const VkMirSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); -typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, MirConnection* connection); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR( - VkInstance instance, - const VkMirSurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); - -VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentationSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - MirConnection* connection); -#endif -#endif /* VK_USE_PLATFORM_MIR_KHR */ +#include "vulkan_core.h" #ifdef VK_USE_PLATFORM_ANDROID_KHR -#define VK_KHR_android_surface 1 -#include - -#define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6 -#define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface" - -typedef VkFlags VkAndroidSurfaceCreateFlagsKHR; - -typedef struct VkAndroidSurfaceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkAndroidSurfaceCreateFlagsKHR flags; - ANativeWindow* window; -} VkAndroidSurfaceCreateInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateAndroidSurfaceKHR)(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR( - VkInstance instance, - const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); -#endif -#endif /* VK_USE_PLATFORM_ANDROID_KHR */ - -#ifdef VK_USE_PLATFORM_WIN32_KHR -#define VK_KHR_win32_surface 1 -#include - -#define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6 -#define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface" - -typedef VkFlags VkWin32SurfaceCreateFlagsKHR; - -typedef struct VkWin32SurfaceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkWin32SurfaceCreateFlagsKHR flags; - HINSTANCE hinstance; - HWND hwnd; -} VkWin32SurfaceCreateInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateWin32SurfaceKHR)(VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); -typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR( - VkInstance instance, - const VkWin32SurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); - -VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex); -#endif -#endif /* VK_USE_PLATFORM_WIN32_KHR */ - -#define VK_KHR_sampler_mirror_clamp_to_edge 1 -#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 1 -#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge" - - -#define VK_KHR_get_physical_device_properties2 1 -#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 1 -#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2" - -typedef struct VkPhysicalDeviceFeatures2KHR { - VkStructureType sType; - void* pNext; - VkPhysicalDeviceFeatures features; -} VkPhysicalDeviceFeatures2KHR; - -typedef struct VkPhysicalDeviceProperties2KHR { - VkStructureType sType; - void* pNext; - VkPhysicalDeviceProperties properties; -} VkPhysicalDeviceProperties2KHR; - -typedef struct VkFormatProperties2KHR { - VkStructureType sType; - void* pNext; - VkFormatProperties formatProperties; -} VkFormatProperties2KHR; - -typedef struct VkImageFormatProperties2KHR { - VkStructureType sType; - void* pNext; - VkImageFormatProperties imageFormatProperties; -} VkImageFormatProperties2KHR; - -typedef struct VkPhysicalDeviceImageFormatInfo2KHR { - VkStructureType sType; - const void* pNext; - VkFormat format; - VkImageType type; - VkImageTiling tiling; - VkImageUsageFlags usage; - VkImageCreateFlags flags; -} VkPhysicalDeviceImageFormatInfo2KHR; - -typedef struct VkQueueFamilyProperties2KHR { - VkStructureType sType; - void* pNext; - VkQueueFamilyProperties queueFamilyProperties; -} VkQueueFamilyProperties2KHR; - -typedef struct VkPhysicalDeviceMemoryProperties2KHR { - VkStructureType sType; - void* pNext; - VkPhysicalDeviceMemoryProperties memoryProperties; -} VkPhysicalDeviceMemoryProperties2KHR; - -typedef struct VkSparseImageFormatProperties2KHR { - VkStructureType sType; - void* pNext; - VkSparseImageFormatProperties properties; -} VkSparseImageFormatProperties2KHR; - -typedef struct VkPhysicalDeviceSparseImageFormatInfo2KHR { - VkStructureType sType; - const void* pNext; - VkFormat format; - VkImageType type; - VkSampleCountFlagBits samples; - VkImageUsageFlags usage; - VkImageTiling tiling; -} VkPhysicalDeviceSparseImageFormatInfo2KHR; - - -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR* pFeatures); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2KHR* pProperties); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2KHR* pFormatProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo, VkImageFormatProperties2KHR* pImageFormatProperties); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2KHR* pQueueFamilyProperties); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2KHR* pProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR( - VkPhysicalDevice physicalDevice, - VkPhysicalDeviceFeatures2KHR* pFeatures); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR( - VkPhysicalDevice physicalDevice, - VkPhysicalDeviceProperties2KHR* pProperties); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR( - VkPhysicalDevice physicalDevice, - VkFormat format, - VkFormatProperties2KHR* pFormatProperties); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo, - VkImageFormatProperties2KHR* pImageFormatProperties); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR( - VkPhysicalDevice physicalDevice, - uint32_t* pQueueFamilyPropertyCount, - VkQueueFamilyProperties2KHR* pQueueFamilyProperties); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR( - VkPhysicalDevice physicalDevice, - VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo, - uint32_t* pPropertyCount, - VkSparseImageFormatProperties2KHR* pProperties); +#include "vulkan_android.h" #endif -#define VK_KHR_shader_draw_parameters 1 -#define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1 -#define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters" - -#define VK_KHR_maintenance1 1 -#define VK_KHR_MAINTENANCE1_SPEC_VERSION 1 -#define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1" - -typedef VkFlags VkCommandPoolTrimFlagsKHR; - -typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlagsKHR flags); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR( - VkDevice device, - VkCommandPool commandPool, - VkCommandPoolTrimFlagsKHR flags); +#ifdef VK_USE_PLATFORM_IOS_MVK +#include "vulkan_ios.h" #endif -#define VK_KHR_external_memory_capabilities 1 -#define VK_LUID_SIZE_KHR 8 -#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities" - -typedef enum VkExternalMemoryHandleTypeFlagBitsKHR { - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = 0x00000001, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = 0x00000002, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = 0x00000004, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR = 0x00000008, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR = 0x00000010, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR = 0x00000020, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR = 0x00000040, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkExternalMemoryHandleTypeFlagBitsKHR; -typedef VkFlags VkExternalMemoryHandleTypeFlagsKHR; - -typedef enum VkExternalMemoryFeatureFlagBitsKHR { - VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR = 0x00000001, - VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR = 0x00000002, - VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR = 0x00000004, - VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkExternalMemoryFeatureFlagBitsKHR; -typedef VkFlags VkExternalMemoryFeatureFlagsKHR; - -typedef struct VkExternalMemoryPropertiesKHR { - VkExternalMemoryFeatureFlagsKHR externalMemoryFeatures; - VkExternalMemoryHandleTypeFlagsKHR exportFromImportedHandleTypes; - VkExternalMemoryHandleTypeFlagsKHR compatibleHandleTypes; -} VkExternalMemoryPropertiesKHR; - -typedef struct VkPhysicalDeviceExternalImageFormatInfoKHR { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagBitsKHR handleType; -} VkPhysicalDeviceExternalImageFormatInfoKHR; - -typedef struct VkExternalImageFormatPropertiesKHR { - VkStructureType sType; - void* pNext; - VkExternalMemoryPropertiesKHR externalMemoryProperties; -} VkExternalImageFormatPropertiesKHR; - -typedef struct VkPhysicalDeviceExternalBufferInfoKHR { - VkStructureType sType; - const void* pNext; - VkBufferCreateFlags flags; - VkBufferUsageFlags usage; - VkExternalMemoryHandleTypeFlagBitsKHR handleType; -} VkPhysicalDeviceExternalBufferInfoKHR; - -typedef struct VkExternalBufferPropertiesKHR { - VkStructureType sType; - void* pNext; - VkExternalMemoryPropertiesKHR externalMemoryProperties; -} VkExternalBufferPropertiesKHR; - -typedef struct VkPhysicalDeviceIDPropertiesKHR { - VkStructureType sType; - void* pNext; - uint8_t deviceUUID[VK_UUID_SIZE]; - uint8_t driverUUID[VK_UUID_SIZE]; - uint8_t deviceLUID[VK_LUID_SIZE_KHR]; - uint32_t deviceNodeMask; - VkBool32 deviceLUIDValid; -} VkPhysicalDeviceIDPropertiesKHR; - - -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfoKHR* pExternalBufferInfo, VkExternalBufferPropertiesKHR* pExternalBufferProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceExternalBufferInfoKHR* pExternalBufferInfo, - VkExternalBufferPropertiesKHR* pExternalBufferProperties); +#ifdef VK_USE_PLATFORM_MACOS_MVK +#include "vulkan_macos.h" #endif -#define VK_KHR_external_memory 1 -#define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory" -#define VK_QUEUE_FAMILY_EXTERNAL_KHR (~0U-1) -typedef struct VkExternalMemoryImageCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagsKHR handleTypes; -} VkExternalMemoryImageCreateInfoKHR; - -typedef struct VkExternalMemoryBufferCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagsKHR handleTypes; -} VkExternalMemoryBufferCreateInfoKHR; - -typedef struct VkExportMemoryAllocateInfoKHR { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagsKHR handleTypes; -} VkExportMemoryAllocateInfoKHR; - - - -#ifdef VK_USE_PLATFORM_WIN32_KHR -#define VK_KHR_external_memory_win32 1 -#define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32" - -typedef struct VkImportMemoryWin32HandleInfoKHR { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagBitsKHR handleType; - HANDLE handle; - LPCWSTR name; -} VkImportMemoryWin32HandleInfoKHR; - -typedef struct VkExportMemoryWin32HandleInfoKHR { - VkStructureType sType; - const void* pNext; - const SECURITY_ATTRIBUTES* pAttributes; - DWORD dwAccess; - LPCWSTR name; -} VkExportMemoryWin32HandleInfoKHR; - -typedef struct VkMemoryWin32HandlePropertiesKHR { - VkStructureType sType; - void* pNext; - uint32_t memoryTypeBits; -} VkMemoryWin32HandlePropertiesKHR; - -typedef struct VkMemoryGetWin32HandleInfoKHR { - VkStructureType sType; - const void* pNext; - VkDeviceMemory memory; - VkExternalMemoryHandleTypeFlagBitsKHR handleType; -} VkMemoryGetWin32HandleInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); -typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBitsKHR handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHR( - VkDevice device, - const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, - HANDLE* pHandle); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR( - VkDevice device, - VkExternalMemoryHandleTypeFlagBitsKHR handleType, - HANDLE handle, - VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties); +#ifdef VK_USE_PLATFORM_MIR_KHR +#include +#include "vulkan_mir.h" #endif -#endif /* VK_USE_PLATFORM_WIN32_KHR */ - -#define VK_KHR_external_memory_fd 1 -#define VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd" - -typedef struct VkImportMemoryFdInfoKHR { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagBitsKHR handleType; - int fd; -} VkImportMemoryFdInfoKHR; - -typedef struct VkMemoryFdPropertiesKHR { - VkStructureType sType; - void* pNext; - uint32_t memoryTypeBits; -} VkMemoryFdPropertiesKHR; - -typedef struct VkMemoryGetFdInfoKHR { - VkStructureType sType; - const void* pNext; - VkDeviceMemory memory; - VkExternalMemoryHandleTypeFlagBitsKHR handleType; -} VkMemoryGetFdInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHR)(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd); -typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBitsKHR handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHR( - VkDevice device, - const VkMemoryGetFdInfoKHR* pGetFdInfo, - int* pFd); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR( - VkDevice device, - VkExternalMemoryHandleTypeFlagBitsKHR handleType, - int fd, - VkMemoryFdPropertiesKHR* pMemoryFdProperties); -#endif - -#ifdef VK_USE_PLATFORM_WIN32_KHR -#define VK_KHR_win32_keyed_mutex 1 -#define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1 -#define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex" - -typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t acquireCount; - const VkDeviceMemory* pAcquireSyncs; - const uint64_t* pAcquireKeys; - const uint32_t* pAcquireTimeouts; - uint32_t releaseCount; - const VkDeviceMemory* pReleaseSyncs; - const uint64_t* pReleaseKeys; -} VkWin32KeyedMutexAcquireReleaseInfoKHR; - - -#endif /* VK_USE_PLATFORM_WIN32_KHR */ - -#define VK_KHR_external_semaphore_capabilities 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities" - - -typedef enum VkExternalSemaphoreHandleTypeFlagBitsKHR { - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = 0x00000001, - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = 0x00000002, - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = 0x00000004, - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR = 0x00000008, - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR = 0x00000010, - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkExternalSemaphoreHandleTypeFlagBitsKHR; -typedef VkFlags VkExternalSemaphoreHandleTypeFlagsKHR; - -typedef enum VkExternalSemaphoreFeatureFlagBitsKHR { - VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR = 0x00000001, - VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR = 0x00000002, - VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkExternalSemaphoreFeatureFlagBitsKHR; -typedef VkFlags VkExternalSemaphoreFeatureFlagsKHR; - -typedef struct VkPhysicalDeviceExternalSemaphoreInfoKHR { - VkStructureType sType; - const void* pNext; - VkExternalSemaphoreHandleTypeFlagBitsKHR handleType; -} VkPhysicalDeviceExternalSemaphoreInfoKHR; - -typedef struct VkExternalSemaphorePropertiesKHR { - VkStructureType sType; - void* pNext; - VkExternalSemaphoreHandleTypeFlagsKHR exportFromImportedHandleTypes; - VkExternalSemaphoreHandleTypeFlagsKHR compatibleHandleTypes; - VkExternalSemaphoreFeatureFlagsKHR externalSemaphoreFeatures; -} VkExternalSemaphorePropertiesKHR; - - -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo, VkExternalSemaphorePropertiesKHR* pExternalSemaphoreProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo, - VkExternalSemaphorePropertiesKHR* pExternalSemaphoreProperties); -#endif - -#define VK_KHR_external_semaphore 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore" - - -typedef enum VkSemaphoreImportFlagBitsKHR { - VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR = 0x00000001, - VK_SEMAPHORE_IMPORT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkSemaphoreImportFlagBitsKHR; -typedef VkFlags VkSemaphoreImportFlagsKHR; - -typedef struct VkExportSemaphoreCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkExternalSemaphoreHandleTypeFlagsKHR handleTypes; -} VkExportSemaphoreCreateInfoKHR; - - - -#ifdef VK_USE_PLATFORM_WIN32_KHR -#define VK_KHR_external_semaphore_win32 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32" - -typedef struct VkImportSemaphoreWin32HandleInfoKHR { - VkStructureType sType; - const void* pNext; - VkSemaphore semaphore; - VkSemaphoreImportFlagsKHR flags; - VkExternalSemaphoreHandleTypeFlagBitsKHR handleType; - HANDLE handle; - LPCWSTR name; -} VkImportSemaphoreWin32HandleInfoKHR; - -typedef struct VkExportSemaphoreWin32HandleInfoKHR { - VkStructureType sType; - const void* pNext; - const SECURITY_ATTRIBUTES* pAttributes; - DWORD dwAccess; - LPCWSTR name; -} VkExportSemaphoreWin32HandleInfoKHR; - -typedef struct VkD3D12FenceSubmitInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t waitSemaphoreValuesCount; - const uint64_t* pWaitSemaphoreValues; - uint32_t signalSemaphoreValuesCount; - const uint64_t* pSignalSemaphoreValues; -} VkD3D12FenceSubmitInfoKHR; - -typedef struct VkSemaphoreGetWin32HandleInfoKHR { - VkStructureType sType; - const void* pNext; - VkSemaphore semaphore; - VkExternalSemaphoreHandleTypeFlagBitsKHR handleType; -} VkSemaphoreGetWin32HandleInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHR)(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo); -typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHR)(VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreWin32HandleKHR( - VkDevice device, - const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR( - VkDevice device, - const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, - HANDLE* pHandle); -#endif -#endif /* VK_USE_PLATFORM_WIN32_KHR */ - -#define VK_KHR_external_semaphore_fd 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd" - -typedef struct VkImportSemaphoreFdInfoKHR { - VkStructureType sType; - const void* pNext; - VkSemaphore semaphore; - VkSemaphoreImportFlagsKHR flags; - VkExternalSemaphoreHandleTypeFlagBitsKHR handleType; - int fd; -} VkImportSemaphoreFdInfoKHR; - -typedef struct VkSemaphoreGetFdInfoKHR { - VkStructureType sType; - const void* pNext; - VkSemaphore semaphore; - VkExternalSemaphoreHandleTypeFlagBitsKHR handleType; -} VkSemaphoreGetFdInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFdKHR)(VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); -typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFdKHR)(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFdKHR( - VkDevice device, - const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHR( - VkDevice device, - const VkSemaphoreGetFdInfoKHR* pGetFdInfo, - int* pFd); -#endif - -#define VK_KHR_push_descriptor 1 -#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 1 -#define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor" - -typedef struct VkPhysicalDevicePushDescriptorPropertiesKHR { - VkStructureType sType; - void* pNext; - uint32_t maxPushDescriptors; -} VkPhysicalDevicePushDescriptorPropertiesKHR; - - -typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetKHR)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR( - VkCommandBuffer commandBuffer, - VkPipelineBindPoint pipelineBindPoint, - VkPipelineLayout layout, - uint32_t set, - uint32_t descriptorWriteCount, - const VkWriteDescriptorSet* pDescriptorWrites); -#endif - -#define VK_KHR_16bit_storage 1 -#define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1 -#define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage" - -typedef struct VkPhysicalDevice16BitStorageFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 storageBuffer16BitAccess; - VkBool32 uniformAndStorageBuffer16BitAccess; - VkBool32 storagePushConstant16; - VkBool32 storageInputOutput16; -} VkPhysicalDevice16BitStorageFeaturesKHR; - - - -#define VK_KHR_incremental_present 1 -#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1 -#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present" - -typedef struct VkRectLayerKHR { - VkOffset2D offset; - VkExtent2D extent; - uint32_t layer; -} VkRectLayerKHR; - -typedef struct VkPresentRegionKHR { - uint32_t rectangleCount; - const VkRectLayerKHR* pRectangles; -} VkPresentRegionKHR; - -typedef struct VkPresentRegionsKHR { - VkStructureType sType; - const void* pNext; - uint32_t swapchainCount; - const VkPresentRegionKHR* pRegions; -} VkPresentRegionsKHR; - - - -#define VK_KHR_descriptor_update_template 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplateKHR) - -#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1 -#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template" - - -typedef enum VkDescriptorUpdateTemplateTypeKHR { - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = 0, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_BEGIN_RANGE_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_END_RANGE_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_RANGE_SIZE_KHR = (VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR + 1), - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkDescriptorUpdateTemplateTypeKHR; - -typedef VkFlags VkDescriptorUpdateTemplateCreateFlagsKHR; - -typedef struct VkDescriptorUpdateTemplateEntryKHR { - uint32_t dstBinding; - uint32_t dstArrayElement; - uint32_t descriptorCount; - VkDescriptorType descriptorType; - size_t offset; - size_t stride; -} VkDescriptorUpdateTemplateEntryKHR; - -typedef struct VkDescriptorUpdateTemplateCreateInfoKHR { - VkStructureType sType; - void* pNext; - VkDescriptorUpdateTemplateCreateFlagsKHR flags; - uint32_t descriptorUpdateEntryCount; - const VkDescriptorUpdateTemplateEntryKHR* pDescriptorUpdateEntries; - VkDescriptorUpdateTemplateTypeKHR templateType; - VkDescriptorSetLayout descriptorSetLayout; - VkPipelineBindPoint pipelineBindPoint; - VkPipelineLayout pipelineLayout; - uint32_t set; -} VkDescriptorUpdateTemplateCreateInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplateKHR* pDescriptorUpdateTemplate); -typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const void* pData); -typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplateKHR( - VkDevice device, - const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDescriptorUpdateTemplateKHR* pDescriptorUpdateTemplate); - -VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplateKHR( - VkDevice device, - VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR( - VkDevice device, - VkDescriptorSet descriptorSet, - VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, - const void* pData); - -VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR( - VkCommandBuffer commandBuffer, - VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, - VkPipelineLayout layout, - uint32_t set, - const void* pData); -#endif - -#define VK_KHR_shared_presentable_image 1 -#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1 -#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image" - -typedef struct VkSharedPresentSurfaceCapabilitiesKHR { - VkStructureType sType; - void* pNext; - VkImageUsageFlags sharedPresentSupportedUsageFlags; -} VkSharedPresentSurfaceCapabilitiesKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR( - VkDevice device, - VkSwapchainKHR swapchain); -#endif - -#define VK_KHR_external_fence_capabilities 1 -#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities" - - -typedef enum VkExternalFenceHandleTypeFlagBitsKHR { - VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = 0x00000001, - VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = 0x00000002, - VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = 0x00000004, - VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR = 0x00000008, - VK_EXTERNAL_FENCE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkExternalFenceHandleTypeFlagBitsKHR; -typedef VkFlags VkExternalFenceHandleTypeFlagsKHR; - -typedef enum VkExternalFenceFeatureFlagBitsKHR { - VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR = 0x00000001, - VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR = 0x00000002, - VK_EXTERNAL_FENCE_FEATURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkExternalFenceFeatureFlagBitsKHR; -typedef VkFlags VkExternalFenceFeatureFlagsKHR; - -typedef struct VkPhysicalDeviceExternalFenceInfoKHR { - VkStructureType sType; - const void* pNext; - VkExternalFenceHandleTypeFlagBitsKHR handleType; -} VkPhysicalDeviceExternalFenceInfoKHR; - -typedef struct VkExternalFencePropertiesKHR { - VkStructureType sType; - void* pNext; - VkExternalFenceHandleTypeFlagsKHR exportFromImportedHandleTypes; - VkExternalFenceHandleTypeFlagsKHR compatibleHandleTypes; - VkExternalFenceFeatureFlagsKHR externalFenceFeatures; -} VkExternalFencePropertiesKHR; - - -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo, VkExternalFencePropertiesKHR* pExternalFenceProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo, - VkExternalFencePropertiesKHR* pExternalFenceProperties); -#endif - -#define VK_KHR_external_fence 1 -#define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence" - - -typedef enum VkFenceImportFlagBitsKHR { - VK_FENCE_IMPORT_TEMPORARY_BIT_KHR = 0x00000001, - VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkFenceImportFlagBitsKHR; -typedef VkFlags VkFenceImportFlagsKHR; - -typedef struct VkExportFenceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkExternalFenceHandleTypeFlagsKHR handleTypes; -} VkExportFenceCreateInfoKHR; - - - -#ifdef VK_USE_PLATFORM_WIN32_KHR -#define VK_KHR_external_fence_win32 1 -#define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32" - -typedef struct VkImportFenceWin32HandleInfoKHR { - VkStructureType sType; - const void* pNext; - VkFence fence; - VkFenceImportFlagsKHR flags; - VkExternalFenceHandleTypeFlagBitsKHR handleType; - HANDLE handle; - LPCWSTR name; -} VkImportFenceWin32HandleInfoKHR; - -typedef struct VkExportFenceWin32HandleInfoKHR { - VkStructureType sType; - const void* pNext; - const SECURITY_ATTRIBUTES* pAttributes; - DWORD dwAccess; - LPCWSTR name; -} VkExportFenceWin32HandleInfoKHR; - -typedef struct VkFenceGetWin32HandleInfoKHR { - VkStructureType sType; - const void* pNext; - VkFence fence; - VkExternalFenceHandleTypeFlagBitsKHR handleType; -} VkFenceGetWin32HandleInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkImportFenceWin32HandleKHR)(VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo); -typedef VkResult (VKAPI_PTR *PFN_vkGetFenceWin32HandleKHR)(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceWin32HandleKHR( - VkDevice device, - const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR( - VkDevice device, - const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, - HANDLE* pHandle); -#endif -#endif /* VK_USE_PLATFORM_WIN32_KHR */ - -#define VK_KHR_external_fence_fd 1 -#define VK_KHR_EXTERNAL_FENCE_FD_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd" - -typedef struct VkImportFenceFdInfoKHR { - VkStructureType sType; - const void* pNext; - VkFence fence; - VkFenceImportFlagsKHR flags; - VkExternalFenceHandleTypeFlagBitsKHR handleType; - int fd; -} VkImportFenceFdInfoKHR; - -typedef struct VkFenceGetFdInfoKHR { - VkStructureType sType; - const void* pNext; - VkFence fence; - VkExternalFenceHandleTypeFlagBitsKHR handleType; -} VkFenceGetFdInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkImportFenceFdKHR)(VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo); -typedef VkResult (VKAPI_PTR *PFN_vkGetFenceFdKHR)(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceFdKHR( - VkDevice device, - const VkImportFenceFdInfoKHR* pImportFenceFdInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceFdKHR( - VkDevice device, - const VkFenceGetFdInfoKHR* pGetFdInfo, - int* pFd); -#endif - -#define VK_KHR_maintenance2 1 -#define VK_KHR_MAINTENANCE2_SPEC_VERSION 1 -#define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2" - - -typedef enum VkPointClippingBehaviorKHR { - VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR = 0, - VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR = 1, - VK_POINT_CLIPPING_BEHAVIOR_BEGIN_RANGE_KHR = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR, - VK_POINT_CLIPPING_BEHAVIOR_END_RANGE_KHR = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR, - VK_POINT_CLIPPING_BEHAVIOR_RANGE_SIZE_KHR = (VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR - VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR + 1), - VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM_KHR = 0x7FFFFFFF -} VkPointClippingBehaviorKHR; - -typedef enum VkTessellationDomainOriginKHR { - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR = 0, - VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR = 1, - VK_TESSELLATION_DOMAIN_ORIGIN_BEGIN_RANGE_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR, - VK_TESSELLATION_DOMAIN_ORIGIN_END_RANGE_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR, - VK_TESSELLATION_DOMAIN_ORIGIN_RANGE_SIZE_KHR = (VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR + 1), - VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM_KHR = 0x7FFFFFFF -} VkTessellationDomainOriginKHR; - -typedef struct VkPhysicalDevicePointClippingPropertiesKHR { - VkStructureType sType; - void* pNext; - VkPointClippingBehaviorKHR pointClippingBehavior; -} VkPhysicalDevicePointClippingPropertiesKHR; - -typedef struct VkInputAttachmentAspectReferenceKHR { - uint32_t subpass; - uint32_t inputAttachmentIndex; - VkImageAspectFlags aspectMask; -} VkInputAttachmentAspectReferenceKHR; - -typedef struct VkRenderPassInputAttachmentAspectCreateInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t aspectReferenceCount; - const VkInputAttachmentAspectReferenceKHR* pAspectReferences; -} VkRenderPassInputAttachmentAspectCreateInfoKHR; - -typedef struct VkImageViewUsageCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkImageUsageFlags usage; -} VkImageViewUsageCreateInfoKHR; - -typedef struct VkPipelineTessellationDomainOriginStateCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkTessellationDomainOriginKHR domainOrigin; -} VkPipelineTessellationDomainOriginStateCreateInfoKHR; - - - -#define VK_KHR_get_surface_capabilities2 1 -#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1 -#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2" - -typedef struct VkPhysicalDeviceSurfaceInfo2KHR { - VkStructureType sType; - const void* pNext; - VkSurfaceKHR surface; -} VkPhysicalDeviceSurfaceInfo2KHR; - -typedef struct VkSurfaceCapabilities2KHR { - VkStructureType sType; - void* pNext; - VkSurfaceCapabilitiesKHR surfaceCapabilities; -} VkSurfaceCapabilities2KHR; - -typedef struct VkSurfaceFormat2KHR { - VkStructureType sType; - void* pNext; - VkSurfaceFormatKHR surfaceFormat; -} VkSurfaceFormat2KHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, - VkSurfaceCapabilities2KHR* pSurfaceCapabilities); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, - uint32_t* pSurfaceFormatCount, - VkSurfaceFormat2KHR* pSurfaceFormats); -#endif - -#define VK_KHR_variable_pointers 1 -#define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1 -#define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers" - -typedef struct VkPhysicalDeviceVariablePointerFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 variablePointersStorageBuffer; - VkBool32 variablePointers; -} VkPhysicalDeviceVariablePointerFeaturesKHR; - - - -#define VK_KHR_dedicated_allocation 1 -#define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3 -#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation" - -typedef struct VkMemoryDedicatedRequirementsKHR { - VkStructureType sType; - void* pNext; - VkBool32 prefersDedicatedAllocation; - VkBool32 requiresDedicatedAllocation; -} VkMemoryDedicatedRequirementsKHR; - -typedef struct VkMemoryDedicatedAllocateInfoKHR { - VkStructureType sType; - const void* pNext; - VkImage image; - VkBuffer buffer; -} VkMemoryDedicatedAllocateInfoKHR; - - - -#define VK_KHR_storage_buffer_storage_class 1 -#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION 1 -#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME "VK_KHR_storage_buffer_storage_class" - - -#define VK_KHR_relaxed_block_layout 1 -#define VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION 1 -#define VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME "VK_KHR_relaxed_block_layout" - - -#define VK_KHR_get_memory_requirements2 1 -#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1 -#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME "VK_KHR_get_memory_requirements2" - -typedef struct VkBufferMemoryRequirementsInfo2KHR { - VkStructureType sType; - const void* pNext; - VkBuffer buffer; -} VkBufferMemoryRequirementsInfo2KHR; - -typedef struct VkImageMemoryRequirementsInfo2KHR { - VkStructureType sType; - const void* pNext; - VkImage image; -} VkImageMemoryRequirementsInfo2KHR; - -typedef struct VkImageSparseMemoryRequirementsInfo2KHR { - VkStructureType sType; - const void* pNext; - VkImage image; -} VkImageSparseMemoryRequirementsInfo2KHR; - -typedef struct VkMemoryRequirements2KHR { - VkStructureType sType; - void* pNext; - VkMemoryRequirements memoryRequirements; -} VkMemoryRequirements2KHR; - -typedef struct VkSparseImageMemoryRequirements2KHR { - VkStructureType sType; - void* pNext; - VkSparseImageMemoryRequirements memoryRequirements; -} VkSparseImageMemoryRequirements2KHR; - - -typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2KHR* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); -typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2KHR* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); -typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2KHR* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2KHR* pSparseMemoryRequirements); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR( - VkDevice device, - const VkImageMemoryRequirementsInfo2KHR* pInfo, - VkMemoryRequirements2KHR* pMemoryRequirements); - -VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2KHR( - VkDevice device, - const VkBufferMemoryRequirementsInfo2KHR* pInfo, - VkMemoryRequirements2KHR* pMemoryRequirements); - -VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR( - VkDevice device, - const VkImageSparseMemoryRequirementsInfo2KHR* pInfo, - uint32_t* pSparseMemoryRequirementCount, - VkSparseImageMemoryRequirements2KHR* pSparseMemoryRequirements); -#endif - -#define VK_KHR_image_format_list 1 -#define VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION 1 -#define VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME "VK_KHR_image_format_list" - -typedef struct VkImageFormatListCreateInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t viewFormatCount; - const VkFormat* pViewFormats; -} VkImageFormatListCreateInfoKHR; - - - -#define VK_KHR_sampler_ycbcr_conversion 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversionKHR) - -#define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 1 -#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion" - - -typedef enum VkSamplerYcbcrModelConversionKHR { - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR = 0, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY_KHR = 1, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR = 2, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR = 3, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR = 4, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_BEGIN_RANGE_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_END_RANGE_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RANGE_SIZE_KHR = (VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR + 1), - VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM_KHR = 0x7FFFFFFF -} VkSamplerYcbcrModelConversionKHR; - -typedef enum VkSamplerYcbcrRangeKHR { - VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR = 0, - VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR = 1, - VK_SAMPLER_YCBCR_RANGE_BEGIN_RANGE_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR, - VK_SAMPLER_YCBCR_RANGE_END_RANGE_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR, - VK_SAMPLER_YCBCR_RANGE_RANGE_SIZE_KHR = (VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR - VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR + 1), - VK_SAMPLER_YCBCR_RANGE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkSamplerYcbcrRangeKHR; - -typedef enum VkChromaLocationKHR { - VK_CHROMA_LOCATION_COSITED_EVEN_KHR = 0, - VK_CHROMA_LOCATION_MIDPOINT_KHR = 1, - VK_CHROMA_LOCATION_BEGIN_RANGE_KHR = VK_CHROMA_LOCATION_COSITED_EVEN_KHR, - VK_CHROMA_LOCATION_END_RANGE_KHR = VK_CHROMA_LOCATION_MIDPOINT_KHR, - VK_CHROMA_LOCATION_RANGE_SIZE_KHR = (VK_CHROMA_LOCATION_MIDPOINT_KHR - VK_CHROMA_LOCATION_COSITED_EVEN_KHR + 1), - VK_CHROMA_LOCATION_MAX_ENUM_KHR = 0x7FFFFFFF -} VkChromaLocationKHR; - -typedef struct VkSamplerYcbcrConversionCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkFormat format; - VkSamplerYcbcrModelConversionKHR ycbcrModel; - VkSamplerYcbcrRangeKHR ycbcrRange; - VkComponentMapping components; - VkChromaLocationKHR xChromaOffset; - VkChromaLocationKHR yChromaOffset; - VkFilter chromaFilter; - VkBool32 forceExplicitReconstruction; -} VkSamplerYcbcrConversionCreateInfoKHR; - -typedef struct VkSamplerYcbcrConversionInfoKHR { - VkStructureType sType; - const void* pNext; - VkSamplerYcbcrConversionKHR conversion; -} VkSamplerYcbcrConversionInfoKHR; - -typedef struct VkBindImagePlaneMemoryInfoKHR { - VkStructureType sType; - const void* pNext; - VkImageAspectFlagBits planeAspect; -} VkBindImagePlaneMemoryInfoKHR; - -typedef struct VkImagePlaneMemoryRequirementsInfoKHR { - VkStructureType sType; - const void* pNext; - VkImageAspectFlagBits planeAspect; -} VkImagePlaneMemoryRequirementsInfoKHR; - -typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 samplerYcbcrConversion; -} VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR; - -typedef struct VkSamplerYcbcrConversionImageFormatPropertiesKHR { - VkStructureType sType; - void* pNext; - uint32_t combinedImageSamplerDescriptorCount; -} VkSamplerYcbcrConversionImageFormatPropertiesKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice device, const VkSamplerYcbcrConversionCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversionKHR* pYcbcrConversion); -typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversionKHR ycbcrConversion, const VkAllocationCallbacks* pAllocator); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversionKHR( - VkDevice device, - const VkSamplerYcbcrConversionCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSamplerYcbcrConversionKHR* pYcbcrConversion); - -VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR( - VkDevice device, - VkSamplerYcbcrConversionKHR ycbcrConversion, - const VkAllocationCallbacks* pAllocator); -#endif - -#define VK_KHR_bind_memory2 1 -#define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1 -#define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2" - -typedef struct VkBindBufferMemoryInfoKHR { - VkStructureType sType; - const void* pNext; - VkBuffer buffer; - VkDeviceMemory memory; - VkDeviceSize memoryOffset; -} VkBindBufferMemoryInfoKHR; - -typedef struct VkBindImageMemoryInfoKHR { - VkStructureType sType; - const void* pNext; - VkImage image; - VkDeviceMemory memory; - VkDeviceSize memoryOffset; -} VkBindImageMemoryInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfoKHR* pBindInfos); -typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfoKHR* pBindInfos); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2KHR( - VkDevice device, - uint32_t bindInfoCount, - const VkBindBufferMemoryInfoKHR* pBindInfos); - -VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR( - VkDevice device, - uint32_t bindInfoCount, - const VkBindImageMemoryInfoKHR* pBindInfos); -#endif - -#define VK_EXT_debug_report 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) - -#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 8 -#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report" -#define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT -#define VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT - - -typedef enum VkDebugReportObjectTypeEXT { - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0, - VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT = 1, - VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT = 2, - VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT = 3, - VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT = 4, - VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT = 5, - VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT = 6, - VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT = 7, - VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT = 8, - VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT = 9, - VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT = 10, - VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT = 11, - VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT = 12, - VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT = 13, - VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT = 14, - VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT = 15, - VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT = 16, - VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT = 17, - VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT = 18, - VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT = 19, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT = 20, - VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT = 21, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT = 22, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT = 23, - VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT = 24, - VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT = 25, - VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26, - VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27, - VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28, - VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29, - VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30, - VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31, - VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32, - VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = 33, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = 1000085000, - VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = 1000156000, - VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1), - VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDebugReportObjectTypeEXT; - - -typedef enum VkDebugReportFlagBitsEXT { - VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0x00000001, - VK_DEBUG_REPORT_WARNING_BIT_EXT = 0x00000002, - VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0x00000004, - VK_DEBUG_REPORT_ERROR_BIT_EXT = 0x00000008, - VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0x00000010, - VK_DEBUG_REPORT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDebugReportFlagBitsEXT; -typedef VkFlags VkDebugReportFlagsEXT; - -typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)( - VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objectType, - uint64_t object, - size_t location, - int32_t messageCode, - const char* pLayerPrefix, - const char* pMessage, - void* pUserData); - -typedef struct VkDebugReportCallbackCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkDebugReportFlagsEXT flags; - PFN_vkDebugReportCallbackEXT pfnCallback; - void* pUserData; -} VkDebugReportCallbackCreateInfoEXT; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback); -typedef void (VKAPI_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkDebugReportMessageEXT)(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT( - VkInstance instance, - const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDebugReportCallbackEXT* pCallback); - -VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT( - VkInstance instance, - VkDebugReportCallbackEXT callback, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT( - VkInstance instance, - VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objectType, - uint64_t object, - size_t location, - int32_t messageCode, - const char* pLayerPrefix, - const char* pMessage); -#endif - -#define VK_NV_glsl_shader 1 -#define VK_NV_GLSL_SHADER_SPEC_VERSION 1 -#define VK_NV_GLSL_SHADER_EXTENSION_NAME "VK_NV_glsl_shader" - - -#define VK_EXT_depth_range_unrestricted 1 -#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION 1 -#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME "VK_EXT_depth_range_unrestricted" - - -#define VK_IMG_filter_cubic 1 -#define VK_IMG_FILTER_CUBIC_SPEC_VERSION 1 -#define VK_IMG_FILTER_CUBIC_EXTENSION_NAME "VK_IMG_filter_cubic" - - -#define VK_AMD_rasterization_order 1 -#define VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION 1 -#define VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME "VK_AMD_rasterization_order" - - -typedef enum VkRasterizationOrderAMD { - VK_RASTERIZATION_ORDER_STRICT_AMD = 0, - VK_RASTERIZATION_ORDER_RELAXED_AMD = 1, - VK_RASTERIZATION_ORDER_BEGIN_RANGE_AMD = VK_RASTERIZATION_ORDER_STRICT_AMD, - VK_RASTERIZATION_ORDER_END_RANGE_AMD = VK_RASTERIZATION_ORDER_RELAXED_AMD, - VK_RASTERIZATION_ORDER_RANGE_SIZE_AMD = (VK_RASTERIZATION_ORDER_RELAXED_AMD - VK_RASTERIZATION_ORDER_STRICT_AMD + 1), - VK_RASTERIZATION_ORDER_MAX_ENUM_AMD = 0x7FFFFFFF -} VkRasterizationOrderAMD; - -typedef struct VkPipelineRasterizationStateRasterizationOrderAMD { - VkStructureType sType; - const void* pNext; - VkRasterizationOrderAMD rasterizationOrder; -} VkPipelineRasterizationStateRasterizationOrderAMD; - - - -#define VK_AMD_shader_trinary_minmax 1 -#define VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION 1 -#define VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME "VK_AMD_shader_trinary_minmax" - - -#define VK_AMD_shader_explicit_vertex_parameter 1 -#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION 1 -#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter" - - -#define VK_EXT_debug_marker 1 -#define VK_EXT_DEBUG_MARKER_SPEC_VERSION 4 -#define VK_EXT_DEBUG_MARKER_EXTENSION_NAME "VK_EXT_debug_marker" - -typedef struct VkDebugMarkerObjectNameInfoEXT { - VkStructureType sType; - const void* pNext; - VkDebugReportObjectTypeEXT objectType; - uint64_t object; - const char* pObjectName; -} VkDebugMarkerObjectNameInfoEXT; - -typedef struct VkDebugMarkerObjectTagInfoEXT { - VkStructureType sType; - const void* pNext; - VkDebugReportObjectTypeEXT objectType; - uint64_t object; - uint64_t tagName; - size_t tagSize; - const void* pTag; -} VkDebugMarkerObjectTagInfoEXT; - -typedef struct VkDebugMarkerMarkerInfoEXT { - VkStructureType sType; - const void* pNext; - const char* pMarkerName; - float color[4]; -} VkDebugMarkerMarkerInfoEXT; - - -typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectTagEXT)(VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo); -typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectNameEXT)(VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo); -typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerBeginEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); -typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerEndEXT)(VkCommandBuffer commandBuffer); -typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerInsertEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectTagEXT( - VkDevice device, - const VkDebugMarkerObjectTagInfoEXT* pTagInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectNameEXT( - VkDevice device, - const VkDebugMarkerObjectNameInfoEXT* pNameInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerBeginEXT( - VkCommandBuffer commandBuffer, - const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerEndEXT( - VkCommandBuffer commandBuffer); - -VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT( - VkCommandBuffer commandBuffer, - const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); -#endif - -#define VK_AMD_gcn_shader 1 -#define VK_AMD_GCN_SHADER_SPEC_VERSION 1 -#define VK_AMD_GCN_SHADER_EXTENSION_NAME "VK_AMD_gcn_shader" - - -#define VK_NV_dedicated_allocation 1 -#define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1 -#define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation" - -typedef struct VkDedicatedAllocationImageCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkBool32 dedicatedAllocation; -} VkDedicatedAllocationImageCreateInfoNV; - -typedef struct VkDedicatedAllocationBufferCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkBool32 dedicatedAllocation; -} VkDedicatedAllocationBufferCreateInfoNV; - -typedef struct VkDedicatedAllocationMemoryAllocateInfoNV { - VkStructureType sType; - const void* pNext; - VkImage image; - VkBuffer buffer; -} VkDedicatedAllocationMemoryAllocateInfoNV; - - - -#define VK_AMD_draw_indirect_count 1 -#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 1 -#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count" - -typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); -typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD( - VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - VkBuffer countBuffer, - VkDeviceSize countBufferOffset, - uint32_t maxDrawCount, - uint32_t stride); - -VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD( - VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - VkBuffer countBuffer, - VkDeviceSize countBufferOffset, - uint32_t maxDrawCount, - uint32_t stride); -#endif - -#define VK_AMD_negative_viewport_height 1 -#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1 -#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height" - - -#define VK_AMD_gpu_shader_half_float 1 -#define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 1 -#define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float" - - -#define VK_AMD_shader_ballot 1 -#define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1 -#define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot" - - -#define VK_AMD_texture_gather_bias_lod 1 -#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION 1 -#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod" - -typedef struct VkTextureLODGatherFormatPropertiesAMD { - VkStructureType sType; - void* pNext; - VkBool32 supportsTextureGatherLODBiasAMD; -} VkTextureLODGatherFormatPropertiesAMD; - - - -#define VK_KHX_multiview 1 -#define VK_KHX_MULTIVIEW_SPEC_VERSION 1 -#define VK_KHX_MULTIVIEW_EXTENSION_NAME "VK_KHX_multiview" - -typedef struct VkRenderPassMultiviewCreateInfoKHX { - VkStructureType sType; - const void* pNext; - uint32_t subpassCount; - const uint32_t* pViewMasks; - uint32_t dependencyCount; - const int32_t* pViewOffsets; - uint32_t correlationMaskCount; - const uint32_t* pCorrelationMasks; -} VkRenderPassMultiviewCreateInfoKHX; - -typedef struct VkPhysicalDeviceMultiviewFeaturesKHX { - VkStructureType sType; - void* pNext; - VkBool32 multiview; - VkBool32 multiviewGeometryShader; - VkBool32 multiviewTessellationShader; -} VkPhysicalDeviceMultiviewFeaturesKHX; - -typedef struct VkPhysicalDeviceMultiviewPropertiesKHX { - VkStructureType sType; - void* pNext; - uint32_t maxMultiviewViewCount; - uint32_t maxMultiviewInstanceIndex; -} VkPhysicalDeviceMultiviewPropertiesKHX; - - - -#define VK_IMG_format_pvrtc 1 -#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1 -#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc" - - -#define VK_NV_external_memory_capabilities 1 -#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 -#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities" - - -typedef enum VkExternalMemoryHandleTypeFlagBitsNV { - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0x00000004, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkExternalMemoryHandleTypeFlagBitsNV; -typedef VkFlags VkExternalMemoryHandleTypeFlagsNV; - -typedef enum VkExternalMemoryFeatureFlagBitsNV { - VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0x00000001, - VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0x00000002, - VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0x00000004, - VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkExternalMemoryFeatureFlagBitsNV; -typedef VkFlags VkExternalMemoryFeatureFlagsNV; - -typedef struct VkExternalImageFormatPropertiesNV { - VkImageFormatProperties imageFormatProperties; - VkExternalMemoryFeatureFlagsNV externalMemoryFeatures; - VkExternalMemoryHandleTypeFlagsNV exportFromImportedHandleTypes; - VkExternalMemoryHandleTypeFlagsNV compatibleHandleTypes; -} VkExternalImageFormatPropertiesNV; - - -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesNV( - VkPhysicalDevice physicalDevice, - VkFormat format, - VkImageType type, - VkImageTiling tiling, - VkImageUsageFlags usage, - VkImageCreateFlags flags, - VkExternalMemoryHandleTypeFlagsNV externalHandleType, - VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); -#endif - -#define VK_NV_external_memory 1 -#define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1 -#define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory" - -typedef struct VkExternalMemoryImageCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagsNV handleTypes; -} VkExternalMemoryImageCreateInfoNV; - -typedef struct VkExportMemoryAllocateInfoNV { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagsNV handleTypes; -} VkExportMemoryAllocateInfoNV; - - - -#ifdef VK_USE_PLATFORM_WIN32_KHR -#define VK_NV_external_memory_win32 1 -#define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 -#define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32" - -typedef struct VkImportMemoryWin32HandleInfoNV { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagsNV handleType; - HANDLE handle; -} VkImportMemoryWin32HandleInfoNV; - -typedef struct VkExportMemoryWin32HandleInfoNV { - VkStructureType sType; - const void* pNext; - const SECURITY_ATTRIBUTES* pAttributes; - DWORD dwAccess; -} VkExportMemoryWin32HandleInfoNV; - - -typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleNV)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV( - VkDevice device, - VkDeviceMemory memory, - VkExternalMemoryHandleTypeFlagsNV handleType, - HANDLE* pHandle); -#endif -#endif /* VK_USE_PLATFORM_WIN32_KHR */ - -#ifdef VK_USE_PLATFORM_WIN32_KHR -#define VK_NV_win32_keyed_mutex 1 -#define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 1 -#define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex" - -typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV { - VkStructureType sType; - const void* pNext; - uint32_t acquireCount; - const VkDeviceMemory* pAcquireSyncs; - const uint64_t* pAcquireKeys; - const uint32_t* pAcquireTimeoutMilliseconds; - uint32_t releaseCount; - const VkDeviceMemory* pReleaseSyncs; - const uint64_t* pReleaseKeys; -} VkWin32KeyedMutexAcquireReleaseInfoNV; - - -#endif /* VK_USE_PLATFORM_WIN32_KHR */ - -#define VK_KHX_device_group 1 -#define VK_KHX_DEVICE_GROUP_SPEC_VERSION 2 -#define VK_KHX_DEVICE_GROUP_EXTENSION_NAME "VK_KHX_device_group" -#define VK_MAX_DEVICE_GROUP_SIZE_KHX 32 - - -typedef enum VkPeerMemoryFeatureFlagBitsKHX { - VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHX = 0x00000001, - VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHX = 0x00000002, - VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHX = 0x00000004, - VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHX = 0x00000008, - VK_PEER_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF -} VkPeerMemoryFeatureFlagBitsKHX; -typedef VkFlags VkPeerMemoryFeatureFlagsKHX; - -typedef enum VkMemoryAllocateFlagBitsKHX { - VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHX = 0x00000001, - VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF -} VkMemoryAllocateFlagBitsKHX; -typedef VkFlags VkMemoryAllocateFlagsKHX; - -typedef enum VkDeviceGroupPresentModeFlagBitsKHX { - VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHX = 0x00000001, - VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHX = 0x00000002, - VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHX = 0x00000004, - VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHX = 0x00000008, - VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF -} VkDeviceGroupPresentModeFlagBitsKHX; -typedef VkFlags VkDeviceGroupPresentModeFlagsKHX; - -typedef struct VkMemoryAllocateFlagsInfoKHX { - VkStructureType sType; - const void* pNext; - VkMemoryAllocateFlagsKHX flags; - uint32_t deviceMask; -} VkMemoryAllocateFlagsInfoKHX; - -typedef struct VkDeviceGroupRenderPassBeginInfoKHX { - VkStructureType sType; - const void* pNext; - uint32_t deviceMask; - uint32_t deviceRenderAreaCount; - const VkRect2D* pDeviceRenderAreas; -} VkDeviceGroupRenderPassBeginInfoKHX; - -typedef struct VkDeviceGroupCommandBufferBeginInfoKHX { - VkStructureType sType; - const void* pNext; - uint32_t deviceMask; -} VkDeviceGroupCommandBufferBeginInfoKHX; - -typedef struct VkDeviceGroupSubmitInfoKHX { - VkStructureType sType; - const void* pNext; - uint32_t waitSemaphoreCount; - const uint32_t* pWaitSemaphoreDeviceIndices; - uint32_t commandBufferCount; - const uint32_t* pCommandBufferDeviceMasks; - uint32_t signalSemaphoreCount; - const uint32_t* pSignalSemaphoreDeviceIndices; -} VkDeviceGroupSubmitInfoKHX; - -typedef struct VkDeviceGroupBindSparseInfoKHX { - VkStructureType sType; - const void* pNext; - uint32_t resourceDeviceIndex; - uint32_t memoryDeviceIndex; -} VkDeviceGroupBindSparseInfoKHX; - -typedef struct VkBindBufferMemoryDeviceGroupInfoKHX { - VkStructureType sType; - const void* pNext; - uint32_t deviceIndexCount; - const uint32_t* pDeviceIndices; -} VkBindBufferMemoryDeviceGroupInfoKHX; - -typedef struct VkBindImageMemoryDeviceGroupInfoKHX { - VkStructureType sType; - const void* pNext; - uint32_t deviceIndexCount; - const uint32_t* pDeviceIndices; - uint32_t SFRRectCount; - const VkRect2D* pSFRRects; -} VkBindImageMemoryDeviceGroupInfoKHX; - -typedef struct VkDeviceGroupPresentCapabilitiesKHX { - VkStructureType sType; - const void* pNext; - uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE_KHX]; - VkDeviceGroupPresentModeFlagsKHX modes; -} VkDeviceGroupPresentCapabilitiesKHX; - -typedef struct VkImageSwapchainCreateInfoKHX { - VkStructureType sType; - const void* pNext; - VkSwapchainKHR swapchain; -} VkImageSwapchainCreateInfoKHX; - -typedef struct VkBindImageMemorySwapchainInfoKHX { - VkStructureType sType; - const void* pNext; - VkSwapchainKHR swapchain; - uint32_t imageIndex; -} VkBindImageMemorySwapchainInfoKHX; - -typedef struct VkAcquireNextImageInfoKHX { - VkStructureType sType; - const void* pNext; - VkSwapchainKHR swapchain; - uint64_t timeout; - VkSemaphore semaphore; - VkFence fence; - uint32_t deviceMask; -} VkAcquireNextImageInfoKHX; - -typedef struct VkDeviceGroupPresentInfoKHX { - VkStructureType sType; - const void* pNext; - uint32_t swapchainCount; - const uint32_t* pDeviceMasks; - VkDeviceGroupPresentModeFlagBitsKHX mode; -} VkDeviceGroupPresentInfoKHX; - -typedef struct VkDeviceGroupSwapchainCreateInfoKHX { - VkStructureType sType; - const void* pNext; - VkDeviceGroupPresentModeFlagsKHX modes; -} VkDeviceGroupSwapchainCreateInfoKHX; - - -typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHX)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlagsKHX* pPeerMemoryFeatures); -typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHX)(VkCommandBuffer commandBuffer, uint32_t deviceMask); -typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHX)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); -typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHX)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHX* pDeviceGroupPresentCapabilities); -typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHX)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHX* pModes); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHX)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects); -typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHX)(VkDevice device, const VkAcquireNextImageInfoKHX* pAcquireInfo, uint32_t* pImageIndex); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHX( - VkDevice device, - uint32_t heapIndex, - uint32_t localDeviceIndex, - uint32_t remoteDeviceIndex, - VkPeerMemoryFeatureFlagsKHX* pPeerMemoryFeatures); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHX( - VkCommandBuffer commandBuffer, - uint32_t deviceMask); - -VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHX( - VkCommandBuffer commandBuffer, - uint32_t baseGroupX, - uint32_t baseGroupY, - uint32_t baseGroupZ, - uint32_t groupCountX, - uint32_t groupCountY, - uint32_t groupCountZ); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHX( - VkDevice device, - VkDeviceGroupPresentCapabilitiesKHX* pDeviceGroupPresentCapabilities); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHX( - VkDevice device, - VkSurfaceKHR surface, - VkDeviceGroupPresentModeFlagsKHX* pModes); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHX( - VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - uint32_t* pRectCount, - VkRect2D* pRects); - -VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHX( - VkDevice device, - const VkAcquireNextImageInfoKHX* pAcquireInfo, - uint32_t* pImageIndex); -#endif - -#define VK_EXT_validation_flags 1 -#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1 -#define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags" - - -typedef enum VkValidationCheckEXT { - VK_VALIDATION_CHECK_ALL_EXT = 0, - VK_VALIDATION_CHECK_SHADERS_EXT = 1, - VK_VALIDATION_CHECK_BEGIN_RANGE_EXT = VK_VALIDATION_CHECK_ALL_EXT, - VK_VALIDATION_CHECK_END_RANGE_EXT = VK_VALIDATION_CHECK_SHADERS_EXT, - VK_VALIDATION_CHECK_RANGE_SIZE_EXT = (VK_VALIDATION_CHECK_SHADERS_EXT - VK_VALIDATION_CHECK_ALL_EXT + 1), - VK_VALIDATION_CHECK_MAX_ENUM_EXT = 0x7FFFFFFF -} VkValidationCheckEXT; - -typedef struct VkValidationFlagsEXT { - VkStructureType sType; - const void* pNext; - uint32_t disabledValidationCheckCount; - VkValidationCheckEXT* pDisabledValidationChecks; -} VkValidationFlagsEXT; - #ifdef VK_USE_PLATFORM_VI_NN -#define VK_NN_vi_surface 1 -#define VK_NN_VI_SURFACE_SPEC_VERSION 1 -#define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface" - -typedef VkFlags VkViSurfaceCreateFlagsNN; - -typedef struct VkViSurfaceCreateInfoNN { - VkStructureType sType; - const void* pNext; - VkViSurfaceCreateFlagsNN flags; - void* window; -} VkViSurfaceCreateInfoNN; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateViSurfaceNN)(VkInstance instance, const VkViSurfaceCreateInfoNN* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateViSurfaceNN( - VkInstance instance, - const VkViSurfaceCreateInfoNN* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); -#endif -#endif /* VK_USE_PLATFORM_VI_NN */ - -#define VK_EXT_shader_subgroup_ballot 1 -#define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1 -#define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot" - - -#define VK_EXT_shader_subgroup_vote 1 -#define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1 -#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote" - - -#define VK_KHX_device_group_creation 1 -#define VK_KHX_DEVICE_GROUP_CREATION_SPEC_VERSION 1 -#define VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHX_device_group_creation" - -typedef struct VkPhysicalDeviceGroupPropertiesKHX { - VkStructureType sType; - void* pNext; - uint32_t physicalDeviceCount; - VkPhysicalDevice physicalDevices[VK_MAX_DEVICE_GROUP_SIZE_KHX]; - VkBool32 subsetAllocation; -} VkPhysicalDeviceGroupPropertiesKHX; - -typedef struct VkDeviceGroupDeviceCreateInfoKHX { - VkStructureType sType; - const void* pNext; - uint32_t physicalDeviceCount; - const VkPhysicalDevice* pPhysicalDevices; -} VkDeviceGroupDeviceCreateInfoKHX; - - -typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHX)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupPropertiesKHX* pPhysicalDeviceGroupProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHX( - VkInstance instance, - uint32_t* pPhysicalDeviceGroupCount, - VkPhysicalDeviceGroupPropertiesKHX* pPhysicalDeviceGroupProperties); +#include "vulkan_vi.h" #endif -#define VK_NVX_device_generated_commands 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX) -#define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 -#define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands" - - -typedef enum VkIndirectCommandsTokenTypeNVX { - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX = 0, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX = 1, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX = 2, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX = 3, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX = 4, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX = 5, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX = 6, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX = 7, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NVX = (VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX + 1), - VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF -} VkIndirectCommandsTokenTypeNVX; - -typedef enum VkObjectEntryTypeNVX { - VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX = 0, - VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX = 1, - VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX = 2, - VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX = 3, - VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX = 4, - VK_OBJECT_ENTRY_TYPE_BEGIN_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX, - VK_OBJECT_ENTRY_TYPE_END_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX, - VK_OBJECT_ENTRY_TYPE_RANGE_SIZE_NVX = (VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX - VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX + 1), - VK_OBJECT_ENTRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF -} VkObjectEntryTypeNVX; - - -typedef enum VkIndirectCommandsLayoutUsageFlagBitsNVX { - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX = 0x00000001, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX = 0x00000002, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX = 0x00000004, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX = 0x00000008, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF -} VkIndirectCommandsLayoutUsageFlagBitsNVX; -typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNVX; - -typedef enum VkObjectEntryUsageFlagBitsNVX { - VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX = 0x00000001, - VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX = 0x00000002, - VK_OBJECT_ENTRY_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF -} VkObjectEntryUsageFlagBitsNVX; -typedef VkFlags VkObjectEntryUsageFlagsNVX; - -typedef struct VkDeviceGeneratedCommandsFeaturesNVX { - VkStructureType sType; - const void* pNext; - VkBool32 computeBindingPointSupport; -} VkDeviceGeneratedCommandsFeaturesNVX; - -typedef struct VkDeviceGeneratedCommandsLimitsNVX { - VkStructureType sType; - const void* pNext; - uint32_t maxIndirectCommandsLayoutTokenCount; - uint32_t maxObjectEntryCounts; - uint32_t minSequenceCountBufferOffsetAlignment; - uint32_t minSequenceIndexBufferOffsetAlignment; - uint32_t minCommandsTokenBufferOffsetAlignment; -} VkDeviceGeneratedCommandsLimitsNVX; - -typedef struct VkIndirectCommandsTokenNVX { - VkIndirectCommandsTokenTypeNVX tokenType; - VkBuffer buffer; - VkDeviceSize offset; -} VkIndirectCommandsTokenNVX; - -typedef struct VkIndirectCommandsLayoutTokenNVX { - VkIndirectCommandsTokenTypeNVX tokenType; - uint32_t bindingUnit; - uint32_t dynamicCount; - uint32_t divisor; -} VkIndirectCommandsLayoutTokenNVX; - -typedef struct VkIndirectCommandsLayoutCreateInfoNVX { - VkStructureType sType; - const void* pNext; - VkPipelineBindPoint pipelineBindPoint; - VkIndirectCommandsLayoutUsageFlagsNVX flags; - uint32_t tokenCount; - const VkIndirectCommandsLayoutTokenNVX* pTokens; -} VkIndirectCommandsLayoutCreateInfoNVX; - -typedef struct VkCmdProcessCommandsInfoNVX { - VkStructureType sType; - const void* pNext; - VkObjectTableNVX objectTable; - VkIndirectCommandsLayoutNVX indirectCommandsLayout; - uint32_t indirectCommandsTokenCount; - const VkIndirectCommandsTokenNVX* pIndirectCommandsTokens; - uint32_t maxSequencesCount; - VkCommandBuffer targetCommandBuffer; - VkBuffer sequencesCountBuffer; - VkDeviceSize sequencesCountOffset; - VkBuffer sequencesIndexBuffer; - VkDeviceSize sequencesIndexOffset; -} VkCmdProcessCommandsInfoNVX; - -typedef struct VkCmdReserveSpaceForCommandsInfoNVX { - VkStructureType sType; - const void* pNext; - VkObjectTableNVX objectTable; - VkIndirectCommandsLayoutNVX indirectCommandsLayout; - uint32_t maxSequencesCount; -} VkCmdReserveSpaceForCommandsInfoNVX; - -typedef struct VkObjectTableCreateInfoNVX { - VkStructureType sType; - const void* pNext; - uint32_t objectCount; - const VkObjectEntryTypeNVX* pObjectEntryTypes; - const uint32_t* pObjectEntryCounts; - const VkObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags; - uint32_t maxUniformBuffersPerDescriptor; - uint32_t maxStorageBuffersPerDescriptor; - uint32_t maxStorageImagesPerDescriptor; - uint32_t maxSampledImagesPerDescriptor; - uint32_t maxPipelineLayouts; -} VkObjectTableCreateInfoNVX; - -typedef struct VkObjectTableEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; -} VkObjectTableEntryNVX; - -typedef struct VkObjectTablePipelineEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkPipeline pipeline; -} VkObjectTablePipelineEntryNVX; - -typedef struct VkObjectTableDescriptorSetEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; -} VkObjectTableDescriptorSetEntryNVX; - -typedef struct VkObjectTableVertexBufferEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkBuffer buffer; -} VkObjectTableVertexBufferEntryNVX; - -typedef struct VkObjectTableIndexBufferEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkBuffer buffer; - VkIndexType indexType; -} VkObjectTableIndexBufferEntryNVX; - -typedef struct VkObjectTablePushConstantEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkPipelineLayout pipelineLayout; - VkShaderStageFlags stageFlags; -} VkObjectTablePushConstantEntryNVX; - - -typedef void (VKAPI_PTR *PFN_vkCmdProcessCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo); -typedef void (VKAPI_PTR *PFN_vkCmdReserveSpaceForCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNVX)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout); -typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNVX)(VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateObjectTableNVX)(VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable); -typedef void (VKAPI_PTR *PFN_vkDestroyObjectTableNVX)(VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkRegisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices); -typedef VkResult (VKAPI_PTR *PFN_vkUnregisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)(VkPhysicalDevice physicalDevice, VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, VkDeviceGeneratedCommandsLimitsNVX* pLimits); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdProcessCommandsNVX( - VkCommandBuffer commandBuffer, - const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdReserveSpaceForCommandsNVX( - VkCommandBuffer commandBuffer, - const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNVX( - VkDevice device, - const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout); - -VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNVX( - VkDevice device, - VkIndirectCommandsLayoutNVX indirectCommandsLayout, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateObjectTableNVX( - VkDevice device, - const VkObjectTableCreateInfoNVX* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkObjectTableNVX* pObjectTable); - -VKAPI_ATTR void VKAPI_CALL vkDestroyObjectTableNVX( - VkDevice device, - VkObjectTableNVX objectTable, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkRegisterObjectsNVX( - VkDevice device, - VkObjectTableNVX objectTable, - uint32_t objectCount, - const VkObjectTableEntryNVX* const* ppObjectTableEntries, - const uint32_t* pObjectIndices); - -VKAPI_ATTR VkResult VKAPI_CALL vkUnregisterObjectsNVX( - VkDevice device, - VkObjectTableNVX objectTable, - uint32_t objectCount, - const VkObjectEntryTypeNVX* pObjectEntryTypes, - const uint32_t* pObjectIndices); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( - VkPhysicalDevice physicalDevice, - VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, - VkDeviceGeneratedCommandsLimitsNVX* pLimits); +#ifdef VK_USE_PLATFORM_WAYLAND_KHR +#include +#include "vulkan_wayland.h" #endif -#define VK_NV_clip_space_w_scaling 1 -#define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1 -#define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling" -typedef struct VkViewportWScalingNV { - float xcoeff; - float ycoeff; -} VkViewportWScalingNV; - -typedef struct VkPipelineViewportWScalingStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkBool32 viewportWScalingEnable; - uint32_t viewportCount; - const VkViewportWScalingNV* pViewportWScalings; -} VkPipelineViewportWScalingStateCreateInfoNV; - - -typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV( - VkCommandBuffer commandBuffer, - uint32_t firstViewport, - uint32_t viewportCount, - const VkViewportWScalingNV* pViewportWScalings); +#ifdef VK_USE_PLATFORM_WIN32_KHR +#include +#include "vulkan_win32.h" #endif -#define VK_EXT_direct_mode_display 1 -#define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1 -#define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display" -typedef VkResult (VKAPI_PTR *PFN_vkReleaseDisplayEXT)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT( - VkPhysicalDevice physicalDevice, - VkDisplayKHR display); +#ifdef VK_USE_PLATFORM_XCB_KHR +#include +#include "vulkan_xcb.h" #endif + +#ifdef VK_USE_PLATFORM_XLIB_KHR +#include +#include "vulkan_xlib.h" +#endif + + #ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT -#define VK_EXT_acquire_xlib_display 1 +#include #include - -#define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1 -#define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display" - -typedef VkResult (VKAPI_PTR *PFN_vkAcquireXlibDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, VkDisplayKHR display); -typedef VkResult (VKAPI_PTR *PFN_vkGetRandROutputDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, RROutput rrOutput, VkDisplayKHR* pDisplay); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkAcquireXlibDisplayEXT( - VkPhysicalDevice physicalDevice, - Display* dpy, - VkDisplayKHR display); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetRandROutputDisplayEXT( - VkPhysicalDevice physicalDevice, - Display* dpy, - RROutput rrOutput, - VkDisplayKHR* pDisplay); -#endif -#endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */ - -#define VK_EXT_display_surface_counter 1 -#define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1 -#define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter" -#define VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT - - -typedef enum VkSurfaceCounterFlagBitsEXT { - VK_SURFACE_COUNTER_VBLANK_EXT = 0x00000001, - VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkSurfaceCounterFlagBitsEXT; -typedef VkFlags VkSurfaceCounterFlagsEXT; - -typedef struct VkSurfaceCapabilities2EXT { - VkStructureType sType; - void* pNext; - uint32_t minImageCount; - uint32_t maxImageCount; - VkExtent2D currentExtent; - VkExtent2D minImageExtent; - VkExtent2D maxImageExtent; - uint32_t maxImageArrayLayers; - VkSurfaceTransformFlagsKHR supportedTransforms; - VkSurfaceTransformFlagBitsKHR currentTransform; - VkCompositeAlphaFlagsKHR supportedCompositeAlpha; - VkImageUsageFlags supportedUsageFlags; - VkSurfaceCounterFlagsEXT supportedSurfaceCounters; -} VkSurfaceCapabilities2EXT; - - -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT( - VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - VkSurfaceCapabilities2EXT* pSurfaceCapabilities); +#include "vulkan_xlib_xrandr.h" #endif -#define VK_EXT_display_control 1 -#define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1 -#define VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME "VK_EXT_display_control" - - -typedef enum VkDisplayPowerStateEXT { - VK_DISPLAY_POWER_STATE_OFF_EXT = 0, - VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1, - VK_DISPLAY_POWER_STATE_ON_EXT = 2, - VK_DISPLAY_POWER_STATE_BEGIN_RANGE_EXT = VK_DISPLAY_POWER_STATE_OFF_EXT, - VK_DISPLAY_POWER_STATE_END_RANGE_EXT = VK_DISPLAY_POWER_STATE_ON_EXT, - VK_DISPLAY_POWER_STATE_RANGE_SIZE_EXT = (VK_DISPLAY_POWER_STATE_ON_EXT - VK_DISPLAY_POWER_STATE_OFF_EXT + 1), - VK_DISPLAY_POWER_STATE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDisplayPowerStateEXT; - -typedef enum VkDeviceEventTypeEXT { - VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0, - VK_DEVICE_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT, - VK_DEVICE_EVENT_TYPE_END_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT, - VK_DEVICE_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT - VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT + 1), - VK_DEVICE_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDeviceEventTypeEXT; - -typedef enum VkDisplayEventTypeEXT { - VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0, - VK_DISPLAY_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT, - VK_DISPLAY_EVENT_TYPE_END_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT, - VK_DISPLAY_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT - VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT + 1), - VK_DISPLAY_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDisplayEventTypeEXT; - -typedef struct VkDisplayPowerInfoEXT { - VkStructureType sType; - const void* pNext; - VkDisplayPowerStateEXT powerState; -} VkDisplayPowerInfoEXT; - -typedef struct VkDeviceEventInfoEXT { - VkStructureType sType; - const void* pNext; - VkDeviceEventTypeEXT deviceEvent; -} VkDeviceEventInfoEXT; - -typedef struct VkDisplayEventInfoEXT { - VkStructureType sType; - const void* pNext; - VkDisplayEventTypeEXT displayEvent; -} VkDisplayEventInfoEXT; - -typedef struct VkSwapchainCounterCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkSurfaceCounterFlagsEXT surfaceCounters; -} VkSwapchainCounterCreateInfoEXT; - - -typedef VkResult (VKAPI_PTR *PFN_vkDisplayPowerControlEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo); -typedef VkResult (VKAPI_PTR *PFN_vkRegisterDeviceEventEXT)(VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); -typedef VkResult (VKAPI_PTR *PFN_vkRegisterDisplayEventEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); -typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainCounterEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkDisplayPowerControlEXT( - VkDevice device, - VkDisplayKHR display, - const VkDisplayPowerInfoEXT* pDisplayPowerInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDeviceEventEXT( - VkDevice device, - const VkDeviceEventInfoEXT* pDeviceEventInfo, - const VkAllocationCallbacks* pAllocator, - VkFence* pFence); - -VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDisplayEventEXT( - VkDevice device, - VkDisplayKHR display, - const VkDisplayEventInfoEXT* pDisplayEventInfo, - const VkAllocationCallbacks* pAllocator, - VkFence* pFence); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT( - VkDevice device, - VkSwapchainKHR swapchain, - VkSurfaceCounterFlagBitsEXT counter, - uint64_t* pCounterValue); -#endif - -#define VK_GOOGLE_display_timing 1 -#define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1 -#define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing" - -typedef struct VkRefreshCycleDurationGOOGLE { - uint64_t refreshDuration; -} VkRefreshCycleDurationGOOGLE; - -typedef struct VkPastPresentationTimingGOOGLE { - uint32_t presentID; - uint64_t desiredPresentTime; - uint64_t actualPresentTime; - uint64_t earliestPresentTime; - uint64_t presentMargin; -} VkPastPresentationTimingGOOGLE; - -typedef struct VkPresentTimeGOOGLE { - uint32_t presentID; - uint64_t desiredPresentTime; -} VkPresentTimeGOOGLE; - -typedef struct VkPresentTimesInfoGOOGLE { - VkStructureType sType; - const void* pNext; - uint32_t swapchainCount; - const VkPresentTimeGOOGLE* pTimes; -} VkPresentTimesInfoGOOGLE; - - -typedef VkResult (VKAPI_PTR *PFN_vkGetRefreshCycleDurationGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetRefreshCycleDurationGOOGLE( - VkDevice device, - VkSwapchainKHR swapchain, - VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( - VkDevice device, - VkSwapchainKHR swapchain, - uint32_t* pPresentationTimingCount, - VkPastPresentationTimingGOOGLE* pPresentationTimings); -#endif - -#define VK_NV_sample_mask_override_coverage 1 -#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1 -#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage" - - -#define VK_NV_geometry_shader_passthrough 1 -#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1 -#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough" - - -#define VK_NV_viewport_array2 1 -#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION 1 -#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME "VK_NV_viewport_array2" - - -#define VK_NVX_multiview_per_view_attributes 1 -#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1 -#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes" - -typedef struct VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX { - VkStructureType sType; - void* pNext; - VkBool32 perViewPositionAllComponents; -} VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX; - - - -#define VK_NV_viewport_swizzle 1 -#define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1 -#define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle" - - -typedef enum VkViewportCoordinateSwizzleNV { - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0, - VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1, - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV = 2, - VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV = 3, - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV = 4, - VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5, - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6, - VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7, - VK_VIEWPORT_COORDINATE_SWIZZLE_BEGIN_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, - VK_VIEWPORT_COORDINATE_SWIZZLE_END_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV, - VK_VIEWPORT_COORDINATE_SWIZZLE_RANGE_SIZE_NV = (VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV + 1), - VK_VIEWPORT_COORDINATE_SWIZZLE_MAX_ENUM_NV = 0x7FFFFFFF -} VkViewportCoordinateSwizzleNV; - -typedef VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV; - -typedef struct VkViewportSwizzleNV { - VkViewportCoordinateSwizzleNV x; - VkViewportCoordinateSwizzleNV y; - VkViewportCoordinateSwizzleNV z; - VkViewportCoordinateSwizzleNV w; -} VkViewportSwizzleNV; - -typedef struct VkPipelineViewportSwizzleStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkPipelineViewportSwizzleStateCreateFlagsNV flags; - uint32_t viewportCount; - const VkViewportSwizzleNV* pViewportSwizzles; -} VkPipelineViewportSwizzleStateCreateInfoNV; - - - -#define VK_EXT_discard_rectangles 1 -#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1 -#define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles" - - -typedef enum VkDiscardRectangleModeEXT { - VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0, - VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1, - VK_DISCARD_RECTANGLE_MODE_BEGIN_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT, - VK_DISCARD_RECTANGLE_MODE_END_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT, - VK_DISCARD_RECTANGLE_MODE_RANGE_SIZE_EXT = (VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT - VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT + 1), - VK_DISCARD_RECTANGLE_MODE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDiscardRectangleModeEXT; - -typedef VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT; - -typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT { - VkStructureType sType; - void* pNext; - uint32_t maxDiscardRectangles; -} VkPhysicalDeviceDiscardRectanglePropertiesEXT; - -typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkPipelineDiscardRectangleStateCreateFlagsEXT flags; - VkDiscardRectangleModeEXT discardRectangleMode; - uint32_t discardRectangleCount; - const VkRect2D* pDiscardRectangles; -} VkPipelineDiscardRectangleStateCreateInfoEXT; - - -typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEXT)(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT( - VkCommandBuffer commandBuffer, - uint32_t firstDiscardRectangle, - uint32_t discardRectangleCount, - const VkRect2D* pDiscardRectangles); -#endif - -#define VK_EXT_swapchain_colorspace 1 -#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 3 -#define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace" - - -#define VK_EXT_hdr_metadata 1 -#define VK_EXT_HDR_METADATA_SPEC_VERSION 1 -#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata" - -typedef struct VkXYColorEXT { - float x; - float y; -} VkXYColorEXT; - -typedef struct VkHdrMetadataEXT { - VkStructureType sType; - const void* pNext; - VkXYColorEXT displayPrimaryRed; - VkXYColorEXT displayPrimaryGreen; - VkXYColorEXT displayPrimaryBlue; - VkXYColorEXT whitePoint; - float maxLuminance; - float minLuminance; - float maxContentLightLevel; - float maxFrameAverageLightLevel; -} VkHdrMetadataEXT; - - -typedef void (VKAPI_PTR *PFN_vkSetHdrMetadataEXT)(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( - VkDevice device, - uint32_t swapchainCount, - const VkSwapchainKHR* pSwapchains, - const VkHdrMetadataEXT* pMetadata); -#endif - -#ifdef VK_USE_PLATFORM_IOS_MVK -#define VK_MVK_ios_surface 1 -#define VK_MVK_IOS_SURFACE_SPEC_VERSION 2 -#define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface" - -typedef VkFlags VkIOSSurfaceCreateFlagsMVK; - -typedef struct VkIOSSurfaceCreateInfoMVK { - VkStructureType sType; - const void* pNext; - VkIOSSurfaceCreateFlagsMVK flags; - const void* pView; -} VkIOSSurfaceCreateInfoMVK; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateIOSSurfaceMVK)(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK( - VkInstance instance, - const VkIOSSurfaceCreateInfoMVK* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); -#endif -#endif /* VK_USE_PLATFORM_IOS_MVK */ - -#ifdef VK_USE_PLATFORM_MACOS_MVK -#define VK_MVK_macos_surface 1 -#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 2 -#define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface" - -typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; - -typedef struct VkMacOSSurfaceCreateInfoMVK { - VkStructureType sType; - const void* pNext; - VkMacOSSurfaceCreateFlagsMVK flags; - const void* pView; -} VkMacOSSurfaceCreateInfoMVK; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateMacOSSurfaceMVK)(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK( - VkInstance instance, - const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); -#endif -#endif /* VK_USE_PLATFORM_MACOS_MVK */ - -#define VK_EXT_sampler_filter_minmax 1 -#define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 1 -#define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME "VK_EXT_sampler_filter_minmax" - - -typedef enum VkSamplerReductionModeEXT { - VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT = 0, - VK_SAMPLER_REDUCTION_MODE_MIN_EXT = 1, - VK_SAMPLER_REDUCTION_MODE_MAX_EXT = 2, - VK_SAMPLER_REDUCTION_MODE_BEGIN_RANGE_EXT = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT, - VK_SAMPLER_REDUCTION_MODE_END_RANGE_EXT = VK_SAMPLER_REDUCTION_MODE_MAX_EXT, - VK_SAMPLER_REDUCTION_MODE_RANGE_SIZE_EXT = (VK_SAMPLER_REDUCTION_MODE_MAX_EXT - VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT + 1), - VK_SAMPLER_REDUCTION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkSamplerReductionModeEXT; - -typedef struct VkSamplerReductionModeCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkSamplerReductionModeEXT reductionMode; -} VkSamplerReductionModeCreateInfoEXT; - -typedef struct VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT { - VkStructureType sType; - void* pNext; - VkBool32 filterMinmaxSingleComponentFormats; - VkBool32 filterMinmaxImageComponentMapping; -} VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT; - - - -#define VK_AMD_gpu_shader_int16 1 -#define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 1 -#define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16" - - -#define VK_AMD_mixed_attachment_samples 1 -#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION 1 -#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME "VK_AMD_mixed_attachment_samples" - - -#define VK_AMD_shader_fragment_mask 1 -#define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1 -#define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask" - - -#define VK_EXT_shader_stencil_export 1 -#define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1 -#define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export" - - -#define VK_EXT_sample_locations 1 -#define VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION 1 -#define VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME "VK_EXT_sample_locations" - -typedef struct VkSampleLocationEXT { - float x; - float y; -} VkSampleLocationEXT; - -typedef struct VkSampleLocationsInfoEXT { - VkStructureType sType; - const void* pNext; - VkSampleCountFlagBits sampleLocationsPerPixel; - VkExtent2D sampleLocationGridSize; - uint32_t sampleLocationsCount; - const VkSampleLocationEXT* pSampleLocations; -} VkSampleLocationsInfoEXT; - -typedef struct VkAttachmentSampleLocationsEXT { - uint32_t attachmentIndex; - VkSampleLocationsInfoEXT sampleLocationsInfo; -} VkAttachmentSampleLocationsEXT; - -typedef struct VkSubpassSampleLocationsEXT { - uint32_t subpassIndex; - VkSampleLocationsInfoEXT sampleLocationsInfo; -} VkSubpassSampleLocationsEXT; - -typedef struct VkRenderPassSampleLocationsBeginInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t attachmentInitialSampleLocationsCount; - const VkAttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations; - uint32_t postSubpassSampleLocationsCount; - const VkSubpassSampleLocationsEXT* pSubpassSampleLocations; -} VkRenderPassSampleLocationsBeginInfoEXT; - -typedef struct VkPipelineSampleLocationsStateCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkBool32 sampleLocationsEnable; - VkSampleLocationsInfoEXT sampleLocationsInfo; -} VkPipelineSampleLocationsStateCreateInfoEXT; - -typedef struct VkPhysicalDeviceSampleLocationsPropertiesEXT { - VkStructureType sType; - void* pNext; - VkSampleCountFlags sampleLocationSampleCounts; - VkExtent2D maxSampleLocationGridSize; - float sampleLocationCoordinateRange[2]; - uint32_t sampleLocationSubPixelBits; - VkBool32 variableSampleLocations; -} VkPhysicalDeviceSampleLocationsPropertiesEXT; - -typedef struct VkMultisamplePropertiesEXT { - VkStructureType sType; - void* pNext; - VkExtent2D maxSampleLocationGridSize; -} VkMultisamplePropertiesEXT; - - -typedef void (VKAPI_PTR *PFN_vkCmdSetSampleLocationsEXT)(VkCommandBuffer commandBuffer, const VkSampleLocationsInfoEXT* pSampleLocationsInfo); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)(VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleLocationsEXT( - VkCommandBuffer commandBuffer, - const VkSampleLocationsInfoEXT* pSampleLocationsInfo); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMultisamplePropertiesEXT( - VkPhysicalDevice physicalDevice, - VkSampleCountFlagBits samples, - VkMultisamplePropertiesEXT* pMultisampleProperties); -#endif - -#define VK_EXT_blend_operation_advanced 1 -#define VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION 2 -#define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME "VK_EXT_blend_operation_advanced" - - -typedef enum VkBlendOverlapEXT { - VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0, - VK_BLEND_OVERLAP_DISJOINT_EXT = 1, - VK_BLEND_OVERLAP_CONJOINT_EXT = 2, - VK_BLEND_OVERLAP_BEGIN_RANGE_EXT = VK_BLEND_OVERLAP_UNCORRELATED_EXT, - VK_BLEND_OVERLAP_END_RANGE_EXT = VK_BLEND_OVERLAP_CONJOINT_EXT, - VK_BLEND_OVERLAP_RANGE_SIZE_EXT = (VK_BLEND_OVERLAP_CONJOINT_EXT - VK_BLEND_OVERLAP_UNCORRELATED_EXT + 1), - VK_BLEND_OVERLAP_MAX_ENUM_EXT = 0x7FFFFFFF -} VkBlendOverlapEXT; - -typedef struct VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 advancedBlendCoherentOperations; -} VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT; - -typedef struct VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT { - VkStructureType sType; - void* pNext; - uint32_t advancedBlendMaxColorAttachments; - VkBool32 advancedBlendIndependentBlend; - VkBool32 advancedBlendNonPremultipliedSrcColor; - VkBool32 advancedBlendNonPremultipliedDstColor; - VkBool32 advancedBlendCorrelatedOverlap; - VkBool32 advancedBlendAllOperations; -} VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT; - -typedef struct VkPipelineColorBlendAdvancedStateCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkBool32 srcPremultiplied; - VkBool32 dstPremultiplied; - VkBlendOverlapEXT blendOverlap; -} VkPipelineColorBlendAdvancedStateCreateInfoEXT; - - - -#define VK_NV_fragment_coverage_to_color 1 -#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION 1 -#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME "VK_NV_fragment_coverage_to_color" - -typedef VkFlags VkPipelineCoverageToColorStateCreateFlagsNV; - -typedef struct VkPipelineCoverageToColorStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkPipelineCoverageToColorStateCreateFlagsNV flags; - VkBool32 coverageToColorEnable; - uint32_t coverageToColorLocation; -} VkPipelineCoverageToColorStateCreateInfoNV; - - - -#define VK_NV_framebuffer_mixed_samples 1 -#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION 1 -#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME "VK_NV_framebuffer_mixed_samples" - - -typedef enum VkCoverageModulationModeNV { - VK_COVERAGE_MODULATION_MODE_NONE_NV = 0, - VK_COVERAGE_MODULATION_MODE_RGB_NV = 1, - VK_COVERAGE_MODULATION_MODE_ALPHA_NV = 2, - VK_COVERAGE_MODULATION_MODE_RGBA_NV = 3, - VK_COVERAGE_MODULATION_MODE_BEGIN_RANGE_NV = VK_COVERAGE_MODULATION_MODE_NONE_NV, - VK_COVERAGE_MODULATION_MODE_END_RANGE_NV = VK_COVERAGE_MODULATION_MODE_RGBA_NV, - VK_COVERAGE_MODULATION_MODE_RANGE_SIZE_NV = (VK_COVERAGE_MODULATION_MODE_RGBA_NV - VK_COVERAGE_MODULATION_MODE_NONE_NV + 1), - VK_COVERAGE_MODULATION_MODE_MAX_ENUM_NV = 0x7FFFFFFF -} VkCoverageModulationModeNV; - -typedef VkFlags VkPipelineCoverageModulationStateCreateFlagsNV; - -typedef struct VkPipelineCoverageModulationStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkPipelineCoverageModulationStateCreateFlagsNV flags; - VkCoverageModulationModeNV coverageModulationMode; - VkBool32 coverageModulationTableEnable; - uint32_t coverageModulationTableCount; - const float* pCoverageModulationTable; -} VkPipelineCoverageModulationStateCreateInfoNV; - - - -#define VK_NV_fill_rectangle 1 -#define VK_NV_FILL_RECTANGLE_SPEC_VERSION 1 -#define VK_NV_FILL_RECTANGLE_EXTENSION_NAME "VK_NV_fill_rectangle" - - -#define VK_EXT_post_depth_coverage 1 -#define VK_EXT_POST_DEPTH_COVERAGE_SPEC_VERSION 1 -#define VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME "VK_EXT_post_depth_coverage" - - -#define VK_EXT_validation_cache 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkValidationCacheEXT) - -#define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1 -#define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache" - - -typedef enum VkValidationCacheHeaderVersionEXT { - VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1, - VK_VALIDATION_CACHE_HEADER_VERSION_BEGIN_RANGE_EXT = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT, - VK_VALIDATION_CACHE_HEADER_VERSION_END_RANGE_EXT = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT, - VK_VALIDATION_CACHE_HEADER_VERSION_RANGE_SIZE_EXT = (VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT - VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT + 1), - VK_VALIDATION_CACHE_HEADER_VERSION_MAX_ENUM_EXT = 0x7FFFFFFF -} VkValidationCacheHeaderVersionEXT; - -typedef VkFlags VkValidationCacheCreateFlagsEXT; - -typedef struct VkValidationCacheCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkValidationCacheCreateFlagsEXT flags; - size_t initialDataSize; - const void* pInitialData; -} VkValidationCacheCreateInfoEXT; - -typedef struct VkShaderModuleValidationCacheCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkValidationCacheEXT validationCache; -} VkShaderModuleValidationCacheCreateInfoEXT; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateValidationCacheEXT)(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache); -typedef void (VKAPI_PTR *PFN_vkDestroyValidationCacheEXT)(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkMergeValidationCachesEXT)(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches); -typedef VkResult (VKAPI_PTR *PFN_vkGetValidationCacheDataEXT)(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateValidationCacheEXT( - VkDevice device, - const VkValidationCacheCreateInfoEXT* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkValidationCacheEXT* pValidationCache); - -VKAPI_ATTR void VKAPI_CALL vkDestroyValidationCacheEXT( - VkDevice device, - VkValidationCacheEXT validationCache, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkMergeValidationCachesEXT( - VkDevice device, - VkValidationCacheEXT dstCache, - uint32_t srcCacheCount, - const VkValidationCacheEXT* pSrcCaches); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetValidationCacheDataEXT( - VkDevice device, - VkValidationCacheEXT validationCache, - size_t* pDataSize, - void* pData); -#endif - -#define VK_EXT_shader_viewport_index_layer 1 -#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1 -#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer" - - -#ifdef __cplusplus -} -#endif - -#endif +#endif // VULKAN_H_ diff --git a/ext/vulkan/vulkan_android.h b/ext/vulkan/vulkan_android.h new file mode 100644 index 0000000000..5e61c0531a --- /dev/null +++ b/ext/vulkan/vulkan_android.h @@ -0,0 +1,60 @@ +#ifndef VULKAN_ANDROID_H_ +#define VULKAN_ANDROID_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2015-2018 The Khronos Group Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#define VK_KHR_android_surface 1 +struct ANativeWindow; + +#define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6 +#define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface" + +typedef VkFlags VkAndroidSurfaceCreateFlagsKHR; + +typedef struct VkAndroidSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkAndroidSurfaceCreateFlagsKHR flags; + struct ANativeWindow* window; +} VkAndroidSurfaceCreateInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAndroidSurfaceKHR)(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR( + VkInstance instance, + const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/vulkan/vulkan_core.h b/ext/vulkan/vulkan_core.h new file mode 100644 index 0000000000..c115fa6616 --- /dev/null +++ b/ext/vulkan/vulkan_core.h @@ -0,0 +1,7334 @@ +#ifndef VULKAN_CORE_H_ +#define VULKAN_CORE_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2015-2018 The Khronos Group Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#define VK_VERSION_1_0 1 +#include "vk_platform.h" + +#define VK_MAKE_VERSION(major, minor, patch) \ + (((major) << 22) | ((minor) << 12) | (patch)) + +// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. +//#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 + +// Vulkan 1.0 version number +#define VK_API_VERSION_1_0 VK_MAKE_VERSION(1, 0, 0)// Patch version should always be set to 0 + +#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) +#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) +#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) +// Version of this file +#define VK_HEADER_VERSION 70 + + +#define VK_NULL_HANDLE 0 + + + +#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; + + +#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE) +#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object; +#else + #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object; +#endif +#endif + + + +typedef uint32_t VkFlags; +typedef uint32_t VkBool32; +typedef uint64_t VkDeviceSize; +typedef uint32_t VkSampleMask; + +VK_DEFINE_HANDLE(VkInstance) +VK_DEFINE_HANDLE(VkPhysicalDevice) +VK_DEFINE_HANDLE(VkDevice) +VK_DEFINE_HANDLE(VkQueue) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore) +VK_DEFINE_HANDLE(VkCommandBuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipeline) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) + +#define VK_LOD_CLAMP_NONE 1000.0f +#define VK_REMAINING_MIP_LEVELS (~0U) +#define VK_REMAINING_ARRAY_LAYERS (~0U) +#define VK_WHOLE_SIZE (~0ULL) +#define VK_ATTACHMENT_UNUSED (~0U) +#define VK_TRUE 1 +#define VK_FALSE 0 +#define VK_QUEUE_FAMILY_IGNORED (~0U) +#define VK_SUBPASS_EXTERNAL (~0U) +#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256 +#define VK_UUID_SIZE 16 +#define VK_MAX_MEMORY_TYPES 32 +#define VK_MAX_MEMORY_HEAPS 16 +#define VK_MAX_EXTENSION_NAME_SIZE 256 +#define VK_MAX_DESCRIPTION_SIZE 256 + + +typedef enum VkPipelineCacheHeaderVersion { + VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, + VK_PIPELINE_CACHE_HEADER_VERSION_BEGIN_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE, + VK_PIPELINE_CACHE_HEADER_VERSION_END_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE, + VK_PIPELINE_CACHE_HEADER_VERSION_RANGE_SIZE = (VK_PIPELINE_CACHE_HEADER_VERSION_ONE - VK_PIPELINE_CACHE_HEADER_VERSION_ONE + 1), + VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheHeaderVersion; + +typedef enum VkResult { + VK_SUCCESS = 0, + VK_NOT_READY = 1, + VK_TIMEOUT = 2, + VK_EVENT_SET = 3, + VK_EVENT_RESET = 4, + VK_INCOMPLETE = 5, + VK_ERROR_OUT_OF_HOST_MEMORY = -1, + VK_ERROR_OUT_OF_DEVICE_MEMORY = -2, + VK_ERROR_INITIALIZATION_FAILED = -3, + VK_ERROR_DEVICE_LOST = -4, + VK_ERROR_MEMORY_MAP_FAILED = -5, + VK_ERROR_LAYER_NOT_PRESENT = -6, + VK_ERROR_EXTENSION_NOT_PRESENT = -7, + VK_ERROR_FEATURE_NOT_PRESENT = -8, + VK_ERROR_INCOMPATIBLE_DRIVER = -9, + VK_ERROR_TOO_MANY_OBJECTS = -10, + VK_ERROR_FORMAT_NOT_SUPPORTED = -11, + VK_ERROR_FRAGMENTED_POOL = -12, + VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000, + VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003, + VK_ERROR_SURFACE_LOST_KHR = -1000000000, + VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001, + VK_SUBOPTIMAL_KHR = 1000001003, + VK_ERROR_OUT_OF_DATE_KHR = -1000001004, + VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, + VK_ERROR_VALIDATION_FAILED_EXT = -1000011001, + VK_ERROR_INVALID_SHADER_NV = -1000012000, + VK_ERROR_NOT_PERMITTED_EXT = -1000174001, + VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY, + VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE, + VK_RESULT_BEGIN_RANGE = VK_ERROR_FRAGMENTED_POOL, + VK_RESULT_END_RANGE = VK_INCOMPLETE, + VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FRAGMENTED_POOL + 1), + VK_RESULT_MAX_ENUM = 0x7FFFFFFF +} VkResult; + +typedef enum VkStructureType { + VK_STRUCTURE_TYPE_APPLICATION_INFO = 0, + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO = 2, + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO = 3, + VK_STRUCTURE_TYPE_SUBMIT_INFO = 4, + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO = 5, + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE = 6, + VK_STRUCTURE_TYPE_BIND_SPARSE_INFO = 7, + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO = 8, + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO = 9, + VK_STRUCTURE_TYPE_EVENT_CREATE_INFO = 10, + VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO = 11, + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO = 12, + VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO = 13, + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO = 14, + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO = 15, + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO = 16, + VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO = 17, + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO = 18, + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 19, + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20, + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO = 21, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO = 22, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO = 23, + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO = 24, + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO = 25, + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO = 26, + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO = 27, + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO = 28, + VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO = 29, + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO = 30, + VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO = 31, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO = 32, + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO = 33, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO = 34, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET = 35, + VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET = 36, + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO = 37, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO = 38, + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO = 39, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO = 40, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO = 41, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO = 42, + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO = 43, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER = 44, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER = 45, + VK_STRUCTURE_TYPE_MEMORY_BARRIER = 46, + VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47, + VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000, + VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO = 1000157000, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO = 1000157001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS = 1000127000, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001, + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO = 1000060000, + VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003, + VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO = 1000060004, + VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO = 1000060005, + VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO = 1000060006, + VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO = 1000060013, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO = 1000060014, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES = 1000070000, + VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO = 1000070001, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 = 1000146000, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 = 1000146001, + VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2 = 1000146002, + VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 = 1000146003, + VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2 = 1000146004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 = 1000059000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 = 1000059001, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 = 1000059002, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 = 1000059003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 = 1000059004, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2 = 1000059005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006, + VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2 = 1000059007, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 = 1000059008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000, + VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001, + VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002, + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003, + VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = 1000120000, + VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO = 1000145000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES = 1000145001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES = 1000145002, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2 = 1000145003, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO = 1000156000, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO = 1000156001, + VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO = 1000156002, + VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO = 1000156003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES = 1000156005, + VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO = 1000071000, + VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES = 1000071001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO = 1000071002, + VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES = 1000071003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES = 1000071004, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO = 1000072000, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO = 1000072001, + VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO = 1000072002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO = 1000112000, + VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES = 1000112001, + VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO = 1000113000, + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO = 1000077000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO = 1000076000, + VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = 1000063000, + VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000, + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001, + VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007, + VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR = 1000060008, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR = 1000060009, + VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR = 1000060010, + VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR = 1000060011, + VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012, + VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR = 1000002000, + VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001, + VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR = 1000003000, + VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000, + VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000, + VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000, + VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000, + VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000, + VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, + VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD = 1000018000, + VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000, + VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001, + VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT = 1000022002, + VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000, + VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001, + VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002, + VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000, + VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000, + VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001, + VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000, + VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000, + VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000, + VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001, + VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002, + VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR = 1000073003, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR = 1000074000, + VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR = 1000074001, + VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR = 1000074002, + VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR = 1000075000, + VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078000, + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078001, + VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR = 1000078002, + VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR = 1000078003, + VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR = 1000079000, + VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR = 1000079001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000, + VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000, + VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001, + VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002, + VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003, + VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004, + VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000, + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT = 1000090000, + VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000, + VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT = 1000091001, + VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT = 1000091002, + VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT = 1000091003, + VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX = 1000097000, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV = 1000098000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT = 1000099000, + VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001, + VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000, + VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000, + VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000, + VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001, + VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR = 1000114002, + VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR = 1000115000, + VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR = 1000115001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000, + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001, + VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002, + VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000, + VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000, + VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000128000, + VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT = 1000128001, + VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT = 1000128002, + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000128003, + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000128004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000, + VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001, + VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000, + VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001, + VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT = 1000143003, + VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT = 1000143004, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR = 1000147000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT = 1000148000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001, + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002, + VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000, + VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000, + VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000, + VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = 1000174000, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000, + VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000, + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001, + VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2, + VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, + VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO, + VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO, + VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO, + VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO, + VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES, + VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES, + VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES, + VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES, + VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO, + VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, + VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2, + VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, + VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO, + VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES, + VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT, + VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO, + VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO, + VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1), + VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkStructureType; + +typedef enum VkSystemAllocationScope { + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1, + VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2, + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3, + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4, + VK_SYSTEM_ALLOCATION_SCOPE_BEGIN_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_COMMAND, + VK_SYSTEM_ALLOCATION_SCOPE_END_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE, + VK_SYSTEM_ALLOCATION_SCOPE_RANGE_SIZE = (VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND + 1), + VK_SYSTEM_ALLOCATION_SCOPE_MAX_ENUM = 0x7FFFFFFF +} VkSystemAllocationScope; + +typedef enum VkInternalAllocationType { + VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0, + VK_INTERNAL_ALLOCATION_TYPE_BEGIN_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE, + VK_INTERNAL_ALLOCATION_TYPE_END_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE, + VK_INTERNAL_ALLOCATION_TYPE_RANGE_SIZE = (VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE - VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE + 1), + VK_INTERNAL_ALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkInternalAllocationType; + +typedef enum VkFormat { + VK_FORMAT_UNDEFINED = 0, + VK_FORMAT_R4G4_UNORM_PACK8 = 1, + VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2, + VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3, + VK_FORMAT_R5G6B5_UNORM_PACK16 = 4, + VK_FORMAT_B5G6R5_UNORM_PACK16 = 5, + VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6, + VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7, + VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8, + VK_FORMAT_R8_UNORM = 9, + VK_FORMAT_R8_SNORM = 10, + VK_FORMAT_R8_USCALED = 11, + VK_FORMAT_R8_SSCALED = 12, + VK_FORMAT_R8_UINT = 13, + VK_FORMAT_R8_SINT = 14, + VK_FORMAT_R8_SRGB = 15, + VK_FORMAT_R8G8_UNORM = 16, + VK_FORMAT_R8G8_SNORM = 17, + VK_FORMAT_R8G8_USCALED = 18, + VK_FORMAT_R8G8_SSCALED = 19, + VK_FORMAT_R8G8_UINT = 20, + VK_FORMAT_R8G8_SINT = 21, + VK_FORMAT_R8G8_SRGB = 22, + VK_FORMAT_R8G8B8_UNORM = 23, + VK_FORMAT_R8G8B8_SNORM = 24, + VK_FORMAT_R8G8B8_USCALED = 25, + VK_FORMAT_R8G8B8_SSCALED = 26, + VK_FORMAT_R8G8B8_UINT = 27, + VK_FORMAT_R8G8B8_SINT = 28, + VK_FORMAT_R8G8B8_SRGB = 29, + VK_FORMAT_B8G8R8_UNORM = 30, + VK_FORMAT_B8G8R8_SNORM = 31, + VK_FORMAT_B8G8R8_USCALED = 32, + VK_FORMAT_B8G8R8_SSCALED = 33, + VK_FORMAT_B8G8R8_UINT = 34, + VK_FORMAT_B8G8R8_SINT = 35, + VK_FORMAT_B8G8R8_SRGB = 36, + VK_FORMAT_R8G8B8A8_UNORM = 37, + VK_FORMAT_R8G8B8A8_SNORM = 38, + VK_FORMAT_R8G8B8A8_USCALED = 39, + VK_FORMAT_R8G8B8A8_SSCALED = 40, + VK_FORMAT_R8G8B8A8_UINT = 41, + VK_FORMAT_R8G8B8A8_SINT = 42, + VK_FORMAT_R8G8B8A8_SRGB = 43, + VK_FORMAT_B8G8R8A8_UNORM = 44, + VK_FORMAT_B8G8R8A8_SNORM = 45, + VK_FORMAT_B8G8R8A8_USCALED = 46, + VK_FORMAT_B8G8R8A8_SSCALED = 47, + VK_FORMAT_B8G8R8A8_UINT = 48, + VK_FORMAT_B8G8R8A8_SINT = 49, + VK_FORMAT_B8G8R8A8_SRGB = 50, + VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51, + VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52, + VK_FORMAT_A8B8G8R8_USCALED_PACK32 = 53, + VK_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54, + VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55, + VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56, + VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57, + VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58, + VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59, + VK_FORMAT_A2R10G10B10_USCALED_PACK32 = 60, + VK_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61, + VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62, + VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63, + VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64, + VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65, + VK_FORMAT_A2B10G10R10_USCALED_PACK32 = 66, + VK_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67, + VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68, + VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69, + VK_FORMAT_R16_UNORM = 70, + VK_FORMAT_R16_SNORM = 71, + VK_FORMAT_R16_USCALED = 72, + VK_FORMAT_R16_SSCALED = 73, + VK_FORMAT_R16_UINT = 74, + VK_FORMAT_R16_SINT = 75, + VK_FORMAT_R16_SFLOAT = 76, + VK_FORMAT_R16G16_UNORM = 77, + VK_FORMAT_R16G16_SNORM = 78, + VK_FORMAT_R16G16_USCALED = 79, + VK_FORMAT_R16G16_SSCALED = 80, + VK_FORMAT_R16G16_UINT = 81, + VK_FORMAT_R16G16_SINT = 82, + VK_FORMAT_R16G16_SFLOAT = 83, + VK_FORMAT_R16G16B16_UNORM = 84, + VK_FORMAT_R16G16B16_SNORM = 85, + VK_FORMAT_R16G16B16_USCALED = 86, + VK_FORMAT_R16G16B16_SSCALED = 87, + VK_FORMAT_R16G16B16_UINT = 88, + VK_FORMAT_R16G16B16_SINT = 89, + VK_FORMAT_R16G16B16_SFLOAT = 90, + VK_FORMAT_R16G16B16A16_UNORM = 91, + VK_FORMAT_R16G16B16A16_SNORM = 92, + VK_FORMAT_R16G16B16A16_USCALED = 93, + VK_FORMAT_R16G16B16A16_SSCALED = 94, + VK_FORMAT_R16G16B16A16_UINT = 95, + VK_FORMAT_R16G16B16A16_SINT = 96, + VK_FORMAT_R16G16B16A16_SFLOAT = 97, + VK_FORMAT_R32_UINT = 98, + VK_FORMAT_R32_SINT = 99, + VK_FORMAT_R32_SFLOAT = 100, + VK_FORMAT_R32G32_UINT = 101, + VK_FORMAT_R32G32_SINT = 102, + VK_FORMAT_R32G32_SFLOAT = 103, + VK_FORMAT_R32G32B32_UINT = 104, + VK_FORMAT_R32G32B32_SINT = 105, + VK_FORMAT_R32G32B32_SFLOAT = 106, + VK_FORMAT_R32G32B32A32_UINT = 107, + VK_FORMAT_R32G32B32A32_SINT = 108, + VK_FORMAT_R32G32B32A32_SFLOAT = 109, + VK_FORMAT_R64_UINT = 110, + VK_FORMAT_R64_SINT = 111, + VK_FORMAT_R64_SFLOAT = 112, + VK_FORMAT_R64G64_UINT = 113, + VK_FORMAT_R64G64_SINT = 114, + VK_FORMAT_R64G64_SFLOAT = 115, + VK_FORMAT_R64G64B64_UINT = 116, + VK_FORMAT_R64G64B64_SINT = 117, + VK_FORMAT_R64G64B64_SFLOAT = 118, + VK_FORMAT_R64G64B64A64_UINT = 119, + VK_FORMAT_R64G64B64A64_SINT = 120, + VK_FORMAT_R64G64B64A64_SFLOAT = 121, + VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122, + VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123, + VK_FORMAT_D16_UNORM = 124, + VK_FORMAT_X8_D24_UNORM_PACK32 = 125, + VK_FORMAT_D32_SFLOAT = 126, + VK_FORMAT_S8_UINT = 127, + VK_FORMAT_D16_UNORM_S8_UINT = 128, + VK_FORMAT_D24_UNORM_S8_UINT = 129, + VK_FORMAT_D32_SFLOAT_S8_UINT = 130, + VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131, + VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132, + VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133, + VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134, + VK_FORMAT_BC2_UNORM_BLOCK = 135, + VK_FORMAT_BC2_SRGB_BLOCK = 136, + VK_FORMAT_BC3_UNORM_BLOCK = 137, + VK_FORMAT_BC3_SRGB_BLOCK = 138, + VK_FORMAT_BC4_UNORM_BLOCK = 139, + VK_FORMAT_BC4_SNORM_BLOCK = 140, + VK_FORMAT_BC5_UNORM_BLOCK = 141, + VK_FORMAT_BC5_SNORM_BLOCK = 142, + VK_FORMAT_BC6H_UFLOAT_BLOCK = 143, + VK_FORMAT_BC6H_SFLOAT_BLOCK = 144, + VK_FORMAT_BC7_UNORM_BLOCK = 145, + VK_FORMAT_BC7_SRGB_BLOCK = 146, + VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147, + VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148, + VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149, + VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150, + VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151, + VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152, + VK_FORMAT_EAC_R11_UNORM_BLOCK = 153, + VK_FORMAT_EAC_R11_SNORM_BLOCK = 154, + VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155, + VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156, + VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157, + VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158, + VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159, + VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160, + VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161, + VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162, + VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163, + VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164, + VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165, + VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166, + VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167, + VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168, + VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169, + VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170, + VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171, + VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172, + VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173, + VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174, + VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175, + VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176, + VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177, + VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178, + VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179, + VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180, + VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181, + VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182, + VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183, + VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184, + VK_FORMAT_G8B8G8R8_422_UNORM = 1000156000, + VK_FORMAT_B8G8R8G8_422_UNORM = 1000156001, + VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM = 1000156002, + VK_FORMAT_G8_B8R8_2PLANE_420_UNORM = 1000156003, + VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM = 1000156004, + VK_FORMAT_G8_B8R8_2PLANE_422_UNORM = 1000156005, + VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM = 1000156006, + VK_FORMAT_R10X6_UNORM_PACK16 = 1000156007, + VK_FORMAT_R10X6G10X6_UNORM_2PACK16 = 1000156008, + VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 = 1000156009, + VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 = 1000156010, + VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 = 1000156011, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 = 1000156012, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 = 1000156013, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 = 1000156014, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 = 1000156015, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 = 1000156016, + VK_FORMAT_R12X4_UNORM_PACK16 = 1000156017, + VK_FORMAT_R12X4G12X4_UNORM_2PACK16 = 1000156018, + VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 = 1000156019, + VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 = 1000156020, + VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 = 1000156021, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 = 1000156022, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 = 1000156023, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 = 1000156024, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 = 1000156025, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 = 1000156026, + VK_FORMAT_G16B16G16R16_422_UNORM = 1000156027, + VK_FORMAT_B16G16R16G16_422_UNORM = 1000156028, + VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM = 1000156029, + VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030, + VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031, + VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032, + VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033, + VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000, + VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001, + VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002, + VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003, + VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004, + VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005, + VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006, + VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007, + VK_FORMAT_G8B8G8R8_422_UNORM_KHR = VK_FORMAT_G8B8G8R8_422_UNORM, + VK_FORMAT_B8G8R8G8_422_UNORM_KHR = VK_FORMAT_B8G8R8G8_422_UNORM, + VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, + VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, + VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, + VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, + VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, + VK_FORMAT_R10X6_UNORM_PACK16_KHR = VK_FORMAT_R10X6_UNORM_PACK16, + VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR = VK_FORMAT_R10X6G10X6_UNORM_2PACK16, + VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, + VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR = VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, + VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, + VK_FORMAT_R12X4_UNORM_PACK16_KHR = VK_FORMAT_R12X4_UNORM_PACK16, + VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR = VK_FORMAT_R12X4G12X4_UNORM_2PACK16, + VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR = VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16, + VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR = VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, + VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR = VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, + VK_FORMAT_G16B16G16R16_422_UNORM_KHR = VK_FORMAT_G16B16G16R16_422_UNORM, + VK_FORMAT_B16G16R16G16_422_UNORM_KHR = VK_FORMAT_B16G16R16G16_422_UNORM, + VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, + VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, + VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, + VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, + VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, + VK_FORMAT_BEGIN_RANGE = VK_FORMAT_UNDEFINED, + VK_FORMAT_END_RANGE = VK_FORMAT_ASTC_12x12_SRGB_BLOCK, + VK_FORMAT_RANGE_SIZE = (VK_FORMAT_ASTC_12x12_SRGB_BLOCK - VK_FORMAT_UNDEFINED + 1), + VK_FORMAT_MAX_ENUM = 0x7FFFFFFF +} VkFormat; + +typedef enum VkImageType { + VK_IMAGE_TYPE_1D = 0, + VK_IMAGE_TYPE_2D = 1, + VK_IMAGE_TYPE_3D = 2, + VK_IMAGE_TYPE_BEGIN_RANGE = VK_IMAGE_TYPE_1D, + VK_IMAGE_TYPE_END_RANGE = VK_IMAGE_TYPE_3D, + VK_IMAGE_TYPE_RANGE_SIZE = (VK_IMAGE_TYPE_3D - VK_IMAGE_TYPE_1D + 1), + VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkImageType; + +typedef enum VkImageTiling { + VK_IMAGE_TILING_OPTIMAL = 0, + VK_IMAGE_TILING_LINEAR = 1, + VK_IMAGE_TILING_BEGIN_RANGE = VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_TILING_END_RANGE = VK_IMAGE_TILING_LINEAR, + VK_IMAGE_TILING_RANGE_SIZE = (VK_IMAGE_TILING_LINEAR - VK_IMAGE_TILING_OPTIMAL + 1), + VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF +} VkImageTiling; + +typedef enum VkPhysicalDeviceType { + VK_PHYSICAL_DEVICE_TYPE_OTHER = 0, + VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1, + VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2, + VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3, + VK_PHYSICAL_DEVICE_TYPE_CPU = 4, + VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE = VK_PHYSICAL_DEVICE_TYPE_OTHER, + VK_PHYSICAL_DEVICE_TYPE_END_RANGE = VK_PHYSICAL_DEVICE_TYPE_CPU, + VK_PHYSICAL_DEVICE_TYPE_RANGE_SIZE = (VK_PHYSICAL_DEVICE_TYPE_CPU - VK_PHYSICAL_DEVICE_TYPE_OTHER + 1), + VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkPhysicalDeviceType; + +typedef enum VkQueryType { + VK_QUERY_TYPE_OCCLUSION = 0, + VK_QUERY_TYPE_PIPELINE_STATISTICS = 1, + VK_QUERY_TYPE_TIMESTAMP = 2, + VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION, + VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_TIMESTAMP, + VK_QUERY_TYPE_RANGE_SIZE = (VK_QUERY_TYPE_TIMESTAMP - VK_QUERY_TYPE_OCCLUSION + 1), + VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkQueryType; + +typedef enum VkSharingMode { + VK_SHARING_MODE_EXCLUSIVE = 0, + VK_SHARING_MODE_CONCURRENT = 1, + VK_SHARING_MODE_BEGIN_RANGE = VK_SHARING_MODE_EXCLUSIVE, + VK_SHARING_MODE_END_RANGE = VK_SHARING_MODE_CONCURRENT, + VK_SHARING_MODE_RANGE_SIZE = (VK_SHARING_MODE_CONCURRENT - VK_SHARING_MODE_EXCLUSIVE + 1), + VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSharingMode; + +typedef enum VkImageLayout { + VK_IMAGE_LAYOUT_UNDEFINED = 0, + VK_IMAGE_LAYOUT_GENERAL = 1, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7, + VK_IMAGE_LAYOUT_PREINITIALIZED = 8, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, + VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_END_RANGE = VK_IMAGE_LAYOUT_PREINITIALIZED, + VK_IMAGE_LAYOUT_RANGE_SIZE = (VK_IMAGE_LAYOUT_PREINITIALIZED - VK_IMAGE_LAYOUT_UNDEFINED + 1), + VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF +} VkImageLayout; + +typedef enum VkImageViewType { + VK_IMAGE_VIEW_TYPE_1D = 0, + VK_IMAGE_VIEW_TYPE_2D = 1, + VK_IMAGE_VIEW_TYPE_3D = 2, + VK_IMAGE_VIEW_TYPE_CUBE = 3, + VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4, + VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5, + VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6, + VK_IMAGE_VIEW_TYPE_BEGIN_RANGE = VK_IMAGE_VIEW_TYPE_1D, + VK_IMAGE_VIEW_TYPE_END_RANGE = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, + VK_IMAGE_VIEW_TYPE_RANGE_SIZE = (VK_IMAGE_VIEW_TYPE_CUBE_ARRAY - VK_IMAGE_VIEW_TYPE_1D + 1), + VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkImageViewType; + +typedef enum VkComponentSwizzle { + VK_COMPONENT_SWIZZLE_IDENTITY = 0, + VK_COMPONENT_SWIZZLE_ZERO = 1, + VK_COMPONENT_SWIZZLE_ONE = 2, + VK_COMPONENT_SWIZZLE_R = 3, + VK_COMPONENT_SWIZZLE_G = 4, + VK_COMPONENT_SWIZZLE_B = 5, + VK_COMPONENT_SWIZZLE_A = 6, + VK_COMPONENT_SWIZZLE_BEGIN_RANGE = VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_END_RANGE = VK_COMPONENT_SWIZZLE_A, + VK_COMPONENT_SWIZZLE_RANGE_SIZE = (VK_COMPONENT_SWIZZLE_A - VK_COMPONENT_SWIZZLE_IDENTITY + 1), + VK_COMPONENT_SWIZZLE_MAX_ENUM = 0x7FFFFFFF +} VkComponentSwizzle; + +typedef enum VkVertexInputRate { + VK_VERTEX_INPUT_RATE_VERTEX = 0, + VK_VERTEX_INPUT_RATE_INSTANCE = 1, + VK_VERTEX_INPUT_RATE_BEGIN_RANGE = VK_VERTEX_INPUT_RATE_VERTEX, + VK_VERTEX_INPUT_RATE_END_RANGE = VK_VERTEX_INPUT_RATE_INSTANCE, + VK_VERTEX_INPUT_RATE_RANGE_SIZE = (VK_VERTEX_INPUT_RATE_INSTANCE - VK_VERTEX_INPUT_RATE_VERTEX + 1), + VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF +} VkVertexInputRate; + +typedef enum VkPrimitiveTopology { + VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0, + VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1, + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5, + VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6, + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9, + VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10, + VK_PRIMITIVE_TOPOLOGY_BEGIN_RANGE = VK_PRIMITIVE_TOPOLOGY_POINT_LIST, + VK_PRIMITIVE_TOPOLOGY_END_RANGE = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, + VK_PRIMITIVE_TOPOLOGY_RANGE_SIZE = (VK_PRIMITIVE_TOPOLOGY_PATCH_LIST - VK_PRIMITIVE_TOPOLOGY_POINT_LIST + 1), + VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF +} VkPrimitiveTopology; + +typedef enum VkPolygonMode { + VK_POLYGON_MODE_FILL = 0, + VK_POLYGON_MODE_LINE = 1, + VK_POLYGON_MODE_POINT = 2, + VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000, + VK_POLYGON_MODE_BEGIN_RANGE = VK_POLYGON_MODE_FILL, + VK_POLYGON_MODE_END_RANGE = VK_POLYGON_MODE_POINT, + VK_POLYGON_MODE_RANGE_SIZE = (VK_POLYGON_MODE_POINT - VK_POLYGON_MODE_FILL + 1), + VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF +} VkPolygonMode; + +typedef enum VkFrontFace { + VK_FRONT_FACE_COUNTER_CLOCKWISE = 0, + VK_FRONT_FACE_CLOCKWISE = 1, + VK_FRONT_FACE_BEGIN_RANGE = VK_FRONT_FACE_COUNTER_CLOCKWISE, + VK_FRONT_FACE_END_RANGE = VK_FRONT_FACE_CLOCKWISE, + VK_FRONT_FACE_RANGE_SIZE = (VK_FRONT_FACE_CLOCKWISE - VK_FRONT_FACE_COUNTER_CLOCKWISE + 1), + VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF +} VkFrontFace; + +typedef enum VkCompareOp { + VK_COMPARE_OP_NEVER = 0, + VK_COMPARE_OP_LESS = 1, + VK_COMPARE_OP_EQUAL = 2, + VK_COMPARE_OP_LESS_OR_EQUAL = 3, + VK_COMPARE_OP_GREATER = 4, + VK_COMPARE_OP_NOT_EQUAL = 5, + VK_COMPARE_OP_GREATER_OR_EQUAL = 6, + VK_COMPARE_OP_ALWAYS = 7, + VK_COMPARE_OP_BEGIN_RANGE = VK_COMPARE_OP_NEVER, + VK_COMPARE_OP_END_RANGE = VK_COMPARE_OP_ALWAYS, + VK_COMPARE_OP_RANGE_SIZE = (VK_COMPARE_OP_ALWAYS - VK_COMPARE_OP_NEVER + 1), + VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF +} VkCompareOp; + +typedef enum VkStencilOp { + VK_STENCIL_OP_KEEP = 0, + VK_STENCIL_OP_ZERO = 1, + VK_STENCIL_OP_REPLACE = 2, + VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3, + VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4, + VK_STENCIL_OP_INVERT = 5, + VK_STENCIL_OP_INCREMENT_AND_WRAP = 6, + VK_STENCIL_OP_DECREMENT_AND_WRAP = 7, + VK_STENCIL_OP_BEGIN_RANGE = VK_STENCIL_OP_KEEP, + VK_STENCIL_OP_END_RANGE = VK_STENCIL_OP_DECREMENT_AND_WRAP, + VK_STENCIL_OP_RANGE_SIZE = (VK_STENCIL_OP_DECREMENT_AND_WRAP - VK_STENCIL_OP_KEEP + 1), + VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF +} VkStencilOp; + +typedef enum VkLogicOp { + VK_LOGIC_OP_CLEAR = 0, + VK_LOGIC_OP_AND = 1, + VK_LOGIC_OP_AND_REVERSE = 2, + VK_LOGIC_OP_COPY = 3, + VK_LOGIC_OP_AND_INVERTED = 4, + VK_LOGIC_OP_NO_OP = 5, + VK_LOGIC_OP_XOR = 6, + VK_LOGIC_OP_OR = 7, + VK_LOGIC_OP_NOR = 8, + VK_LOGIC_OP_EQUIVALENT = 9, + VK_LOGIC_OP_INVERT = 10, + VK_LOGIC_OP_OR_REVERSE = 11, + VK_LOGIC_OP_COPY_INVERTED = 12, + VK_LOGIC_OP_OR_INVERTED = 13, + VK_LOGIC_OP_NAND = 14, + VK_LOGIC_OP_SET = 15, + VK_LOGIC_OP_BEGIN_RANGE = VK_LOGIC_OP_CLEAR, + VK_LOGIC_OP_END_RANGE = VK_LOGIC_OP_SET, + VK_LOGIC_OP_RANGE_SIZE = (VK_LOGIC_OP_SET - VK_LOGIC_OP_CLEAR + 1), + VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF +} VkLogicOp; + +typedef enum VkBlendFactor { + VK_BLEND_FACTOR_ZERO = 0, + VK_BLEND_FACTOR_ONE = 1, + VK_BLEND_FACTOR_SRC_COLOR = 2, + VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = 3, + VK_BLEND_FACTOR_DST_COLOR = 4, + VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR = 5, + VK_BLEND_FACTOR_SRC_ALPHA = 6, + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = 7, + VK_BLEND_FACTOR_DST_ALPHA = 8, + VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = 9, + VK_BLEND_FACTOR_CONSTANT_COLOR = 10, + VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR = 11, + VK_BLEND_FACTOR_CONSTANT_ALPHA = 12, + VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = 13, + VK_BLEND_FACTOR_SRC_ALPHA_SATURATE = 14, + VK_BLEND_FACTOR_SRC1_COLOR = 15, + VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16, + VK_BLEND_FACTOR_SRC1_ALPHA = 17, + VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18, + VK_BLEND_FACTOR_BEGIN_RANGE = VK_BLEND_FACTOR_ZERO, + VK_BLEND_FACTOR_END_RANGE = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, + VK_BLEND_FACTOR_RANGE_SIZE = (VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA - VK_BLEND_FACTOR_ZERO + 1), + VK_BLEND_FACTOR_MAX_ENUM = 0x7FFFFFFF +} VkBlendFactor; + +typedef enum VkBlendOp { + VK_BLEND_OP_ADD = 0, + VK_BLEND_OP_SUBTRACT = 1, + VK_BLEND_OP_REVERSE_SUBTRACT = 2, + VK_BLEND_OP_MIN = 3, + VK_BLEND_OP_MAX = 4, + VK_BLEND_OP_ZERO_EXT = 1000148000, + VK_BLEND_OP_SRC_EXT = 1000148001, + VK_BLEND_OP_DST_EXT = 1000148002, + VK_BLEND_OP_SRC_OVER_EXT = 1000148003, + VK_BLEND_OP_DST_OVER_EXT = 1000148004, + VK_BLEND_OP_SRC_IN_EXT = 1000148005, + VK_BLEND_OP_DST_IN_EXT = 1000148006, + VK_BLEND_OP_SRC_OUT_EXT = 1000148007, + VK_BLEND_OP_DST_OUT_EXT = 1000148008, + VK_BLEND_OP_SRC_ATOP_EXT = 1000148009, + VK_BLEND_OP_DST_ATOP_EXT = 1000148010, + VK_BLEND_OP_XOR_EXT = 1000148011, + VK_BLEND_OP_MULTIPLY_EXT = 1000148012, + VK_BLEND_OP_SCREEN_EXT = 1000148013, + VK_BLEND_OP_OVERLAY_EXT = 1000148014, + VK_BLEND_OP_DARKEN_EXT = 1000148015, + VK_BLEND_OP_LIGHTEN_EXT = 1000148016, + VK_BLEND_OP_COLORDODGE_EXT = 1000148017, + VK_BLEND_OP_COLORBURN_EXT = 1000148018, + VK_BLEND_OP_HARDLIGHT_EXT = 1000148019, + VK_BLEND_OP_SOFTLIGHT_EXT = 1000148020, + VK_BLEND_OP_DIFFERENCE_EXT = 1000148021, + VK_BLEND_OP_EXCLUSION_EXT = 1000148022, + VK_BLEND_OP_INVERT_EXT = 1000148023, + VK_BLEND_OP_INVERT_RGB_EXT = 1000148024, + VK_BLEND_OP_LINEARDODGE_EXT = 1000148025, + VK_BLEND_OP_LINEARBURN_EXT = 1000148026, + VK_BLEND_OP_VIVIDLIGHT_EXT = 1000148027, + VK_BLEND_OP_LINEARLIGHT_EXT = 1000148028, + VK_BLEND_OP_PINLIGHT_EXT = 1000148029, + VK_BLEND_OP_HARDMIX_EXT = 1000148030, + VK_BLEND_OP_HSL_HUE_EXT = 1000148031, + VK_BLEND_OP_HSL_SATURATION_EXT = 1000148032, + VK_BLEND_OP_HSL_COLOR_EXT = 1000148033, + VK_BLEND_OP_HSL_LUMINOSITY_EXT = 1000148034, + VK_BLEND_OP_PLUS_EXT = 1000148035, + VK_BLEND_OP_PLUS_CLAMPED_EXT = 1000148036, + VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT = 1000148037, + VK_BLEND_OP_PLUS_DARKER_EXT = 1000148038, + VK_BLEND_OP_MINUS_EXT = 1000148039, + VK_BLEND_OP_MINUS_CLAMPED_EXT = 1000148040, + VK_BLEND_OP_CONTRAST_EXT = 1000148041, + VK_BLEND_OP_INVERT_OVG_EXT = 1000148042, + VK_BLEND_OP_RED_EXT = 1000148043, + VK_BLEND_OP_GREEN_EXT = 1000148044, + VK_BLEND_OP_BLUE_EXT = 1000148045, + VK_BLEND_OP_BEGIN_RANGE = VK_BLEND_OP_ADD, + VK_BLEND_OP_END_RANGE = VK_BLEND_OP_MAX, + VK_BLEND_OP_RANGE_SIZE = (VK_BLEND_OP_MAX - VK_BLEND_OP_ADD + 1), + VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF +} VkBlendOp; + +typedef enum VkDynamicState { + VK_DYNAMIC_STATE_VIEWPORT = 0, + VK_DYNAMIC_STATE_SCISSOR = 1, + VK_DYNAMIC_STATE_LINE_WIDTH = 2, + VK_DYNAMIC_STATE_DEPTH_BIAS = 3, + VK_DYNAMIC_STATE_BLEND_CONSTANTS = 4, + VK_DYNAMIC_STATE_DEPTH_BOUNDS = 5, + VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6, + VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7, + VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8, + VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000, + VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000, + VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000, + VK_DYNAMIC_STATE_BEGIN_RANGE = VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_END_RANGE = VK_DYNAMIC_STATE_STENCIL_REFERENCE, + VK_DYNAMIC_STATE_RANGE_SIZE = (VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1), + VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF +} VkDynamicState; + +typedef enum VkFilter { + VK_FILTER_NEAREST = 0, + VK_FILTER_LINEAR = 1, + VK_FILTER_CUBIC_IMG = 1000015000, + VK_FILTER_BEGIN_RANGE = VK_FILTER_NEAREST, + VK_FILTER_END_RANGE = VK_FILTER_LINEAR, + VK_FILTER_RANGE_SIZE = (VK_FILTER_LINEAR - VK_FILTER_NEAREST + 1), + VK_FILTER_MAX_ENUM = 0x7FFFFFFF +} VkFilter; + +typedef enum VkSamplerMipmapMode { + VK_SAMPLER_MIPMAP_MODE_NEAREST = 0, + VK_SAMPLER_MIPMAP_MODE_LINEAR = 1, + VK_SAMPLER_MIPMAP_MODE_BEGIN_RANGE = VK_SAMPLER_MIPMAP_MODE_NEAREST, + VK_SAMPLER_MIPMAP_MODE_END_RANGE = VK_SAMPLER_MIPMAP_MODE_LINEAR, + VK_SAMPLER_MIPMAP_MODE_RANGE_SIZE = (VK_SAMPLER_MIPMAP_MODE_LINEAR - VK_SAMPLER_MIPMAP_MODE_NEAREST + 1), + VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerMipmapMode; + +typedef enum VkSamplerAddressMode { + VK_SAMPLER_ADDRESS_MODE_REPEAT = 0, + VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1, + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2, + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, + VK_SAMPLER_ADDRESS_MODE_BEGIN_RANGE = VK_SAMPLER_ADDRESS_MODE_REPEAT, + VK_SAMPLER_ADDRESS_MODE_END_RANGE = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, + VK_SAMPLER_ADDRESS_MODE_RANGE_SIZE = (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER - VK_SAMPLER_ADDRESS_MODE_REPEAT + 1), + VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerAddressMode; + +typedef enum VkBorderColor { + VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0, + VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1, + VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2, + VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3, + VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4, + VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5, + VK_BORDER_COLOR_BEGIN_RANGE = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, + VK_BORDER_COLOR_END_RANGE = VK_BORDER_COLOR_INT_OPAQUE_WHITE, + VK_BORDER_COLOR_RANGE_SIZE = (VK_BORDER_COLOR_INT_OPAQUE_WHITE - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK + 1), + VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF +} VkBorderColor; + +typedef enum VkDescriptorType { + VK_DESCRIPTOR_TYPE_SAMPLER = 0, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1, + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2, + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4, + VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, + VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER, + VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1), + VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorType; + +typedef enum VkAttachmentLoadOp { + VK_ATTACHMENT_LOAD_OP_LOAD = 0, + VK_ATTACHMENT_LOAD_OP_CLEAR = 1, + VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2, + VK_ATTACHMENT_LOAD_OP_BEGIN_RANGE = VK_ATTACHMENT_LOAD_OP_LOAD, + VK_ATTACHMENT_LOAD_OP_END_RANGE = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + VK_ATTACHMENT_LOAD_OP_RANGE_SIZE = (VK_ATTACHMENT_LOAD_OP_DONT_CARE - VK_ATTACHMENT_LOAD_OP_LOAD + 1), + VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF +} VkAttachmentLoadOp; + +typedef enum VkAttachmentStoreOp { + VK_ATTACHMENT_STORE_OP_STORE = 0, + VK_ATTACHMENT_STORE_OP_DONT_CARE = 1, + VK_ATTACHMENT_STORE_OP_BEGIN_RANGE = VK_ATTACHMENT_STORE_OP_STORE, + VK_ATTACHMENT_STORE_OP_END_RANGE = VK_ATTACHMENT_STORE_OP_DONT_CARE, + VK_ATTACHMENT_STORE_OP_RANGE_SIZE = (VK_ATTACHMENT_STORE_OP_DONT_CARE - VK_ATTACHMENT_STORE_OP_STORE + 1), + VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF +} VkAttachmentStoreOp; + +typedef enum VkPipelineBindPoint { + VK_PIPELINE_BIND_POINT_GRAPHICS = 0, + VK_PIPELINE_BIND_POINT_COMPUTE = 1, + VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS, + VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE, + VK_PIPELINE_BIND_POINT_RANGE_SIZE = (VK_PIPELINE_BIND_POINT_COMPUTE - VK_PIPELINE_BIND_POINT_GRAPHICS + 1), + VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF +} VkPipelineBindPoint; + +typedef enum VkCommandBufferLevel { + VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0, + VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1, + VK_COMMAND_BUFFER_LEVEL_BEGIN_RANGE = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + VK_COMMAND_BUFFER_LEVEL_END_RANGE = VK_COMMAND_BUFFER_LEVEL_SECONDARY, + VK_COMMAND_BUFFER_LEVEL_RANGE_SIZE = (VK_COMMAND_BUFFER_LEVEL_SECONDARY - VK_COMMAND_BUFFER_LEVEL_PRIMARY + 1), + VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF +} VkCommandBufferLevel; + +typedef enum VkIndexType { + VK_INDEX_TYPE_UINT16 = 0, + VK_INDEX_TYPE_UINT32 = 1, + VK_INDEX_TYPE_BEGIN_RANGE = VK_INDEX_TYPE_UINT16, + VK_INDEX_TYPE_END_RANGE = VK_INDEX_TYPE_UINT32, + VK_INDEX_TYPE_RANGE_SIZE = (VK_INDEX_TYPE_UINT32 - VK_INDEX_TYPE_UINT16 + 1), + VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkIndexType; + +typedef enum VkSubpassContents { + VK_SUBPASS_CONTENTS_INLINE = 0, + VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1, + VK_SUBPASS_CONTENTS_BEGIN_RANGE = VK_SUBPASS_CONTENTS_INLINE, + VK_SUBPASS_CONTENTS_END_RANGE = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, + VK_SUBPASS_CONTENTS_RANGE_SIZE = (VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS - VK_SUBPASS_CONTENTS_INLINE + 1), + VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF +} VkSubpassContents; + +typedef enum VkObjectType { + VK_OBJECT_TYPE_UNKNOWN = 0, + VK_OBJECT_TYPE_INSTANCE = 1, + VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2, + VK_OBJECT_TYPE_DEVICE = 3, + VK_OBJECT_TYPE_QUEUE = 4, + VK_OBJECT_TYPE_SEMAPHORE = 5, + VK_OBJECT_TYPE_COMMAND_BUFFER = 6, + VK_OBJECT_TYPE_FENCE = 7, + VK_OBJECT_TYPE_DEVICE_MEMORY = 8, + VK_OBJECT_TYPE_BUFFER = 9, + VK_OBJECT_TYPE_IMAGE = 10, + VK_OBJECT_TYPE_EVENT = 11, + VK_OBJECT_TYPE_QUERY_POOL = 12, + VK_OBJECT_TYPE_BUFFER_VIEW = 13, + VK_OBJECT_TYPE_IMAGE_VIEW = 14, + VK_OBJECT_TYPE_SHADER_MODULE = 15, + VK_OBJECT_TYPE_PIPELINE_CACHE = 16, + VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17, + VK_OBJECT_TYPE_RENDER_PASS = 18, + VK_OBJECT_TYPE_PIPELINE = 19, + VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20, + VK_OBJECT_TYPE_SAMPLER = 21, + VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22, + VK_OBJECT_TYPE_DESCRIPTOR_SET = 23, + VK_OBJECT_TYPE_FRAMEBUFFER = 24, + VK_OBJECT_TYPE_COMMAND_POOL = 25, + VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000, + VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000, + VK_OBJECT_TYPE_SURFACE_KHR = 1000000000, + VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000, + VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000, + VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001, + VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000, + VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000, + VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001, + VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000, + VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000, + VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, + VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, + VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN, + VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_COMMAND_POOL, + VK_OBJECT_TYPE_RANGE_SIZE = (VK_OBJECT_TYPE_COMMAND_POOL - VK_OBJECT_TYPE_UNKNOWN + 1), + VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkObjectType; + +typedef VkFlags VkInstanceCreateFlags; + +typedef enum VkFormatFeatureFlagBits { + VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001, + VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0x00000002, + VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004, + VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008, + VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT = 0x00000010, + VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020, + VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT = 0x00000040, + VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT = 0x00000080, + VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200, + VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0x00000400, + VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000, + VK_FORMAT_FEATURE_TRANSFER_SRC_BIT = 0x00004000, + VK_FORMAT_FEATURE_TRANSFER_DST_BIT = 0x00008000, + VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT = 0x00020000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0x00040000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0x00080000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0x00100000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0x00200000, + VK_FORMAT_FEATURE_DISJOINT_BIT = 0x00400000, + VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = 0x00010000, + VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT, + VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT, + VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT, + VK_FORMAT_FEATURE_DISJOINT_BIT_KHR = VK_FORMAT_FEATURE_DISJOINT_BIT, + VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, + VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFormatFeatureFlagBits; +typedef VkFlags VkFormatFeatureFlags; + +typedef enum VkImageUsageFlagBits { + VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001, + VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002, + VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004, + VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, + VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, + VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageUsageFlagBits; +typedef VkFlags VkImageUsageFlags; + +typedef enum VkImageCreateFlagBits { + VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0x00000001, + VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, + VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004, + VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008, + VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010, + VK_IMAGE_CREATE_ALIAS_BIT = 0x00000400, + VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT = 0x00000040, + VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT = 0x00000020, + VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT = 0x00000080, + VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0x00000100, + VK_IMAGE_CREATE_PROTECTED_BIT = 0x00000800, + VK_IMAGE_CREATE_DISJOINT_BIT = 0x00000200, + VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000, + VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT, + VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, + VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT, + VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR = VK_IMAGE_CREATE_EXTENDED_USAGE_BIT, + VK_IMAGE_CREATE_DISJOINT_BIT_KHR = VK_IMAGE_CREATE_DISJOINT_BIT, + VK_IMAGE_CREATE_ALIAS_BIT_KHR = VK_IMAGE_CREATE_ALIAS_BIT, + VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageCreateFlagBits; +typedef VkFlags VkImageCreateFlags; + +typedef enum VkSampleCountFlagBits { + VK_SAMPLE_COUNT_1_BIT = 0x00000001, + VK_SAMPLE_COUNT_2_BIT = 0x00000002, + VK_SAMPLE_COUNT_4_BIT = 0x00000004, + VK_SAMPLE_COUNT_8_BIT = 0x00000008, + VK_SAMPLE_COUNT_16_BIT = 0x00000010, + VK_SAMPLE_COUNT_32_BIT = 0x00000020, + VK_SAMPLE_COUNT_64_BIT = 0x00000040, + VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSampleCountFlagBits; +typedef VkFlags VkSampleCountFlags; + +typedef enum VkQueueFlagBits { + VK_QUEUE_GRAPHICS_BIT = 0x00000001, + VK_QUEUE_COMPUTE_BIT = 0x00000002, + VK_QUEUE_TRANSFER_BIT = 0x00000004, + VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, + VK_QUEUE_PROTECTED_BIT = 0x00000010, + VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueueFlagBits; +typedef VkFlags VkQueueFlags; + +typedef enum VkMemoryPropertyFlagBits { + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002, + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008, + VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010, + VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020, + VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryPropertyFlagBits; +typedef VkFlags VkMemoryPropertyFlags; + +typedef enum VkMemoryHeapFlagBits { + VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001, + VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002, + VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT, + VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryHeapFlagBits; +typedef VkFlags VkMemoryHeapFlags; +typedef VkFlags VkDeviceCreateFlags; + +typedef enum VkDeviceQueueCreateFlagBits { + VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 0x00000001, + VK_DEVICE_QUEUE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDeviceQueueCreateFlagBits; +typedef VkFlags VkDeviceQueueCreateFlags; + +typedef enum VkPipelineStageFlagBits { + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001, + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004, + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008, + VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010, + VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020, + VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0x00000040, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100, + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0x00000800, + VK_PIPELINE_STAGE_TRANSFER_BIT = 0x00001000, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0x00002000, + VK_PIPELINE_STAGE_HOST_BIT = 0x00004000, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000, + VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000, + VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineStageFlagBits; +typedef VkFlags VkPipelineStageFlags; +typedef VkFlags VkMemoryMapFlags; + +typedef enum VkImageAspectFlagBits { + VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001, + VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002, + VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004, + VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008, + VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010, + VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020, + VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040, + VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = VK_IMAGE_ASPECT_PLANE_0_BIT, + VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = VK_IMAGE_ASPECT_PLANE_1_BIT, + VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = VK_IMAGE_ASPECT_PLANE_2_BIT, + VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageAspectFlagBits; +typedef VkFlags VkImageAspectFlags; + +typedef enum VkSparseImageFormatFlagBits { + VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001, + VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 0x00000002, + VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 0x00000004, + VK_SPARSE_IMAGE_FORMAT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSparseImageFormatFlagBits; +typedef VkFlags VkSparseImageFormatFlags; + +typedef enum VkSparseMemoryBindFlagBits { + VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001, + VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSparseMemoryBindFlagBits; +typedef VkFlags VkSparseMemoryBindFlags; + +typedef enum VkFenceCreateFlagBits { + VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001, + VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFenceCreateFlagBits; +typedef VkFlags VkFenceCreateFlags; +typedef VkFlags VkSemaphoreCreateFlags; +typedef VkFlags VkEventCreateFlags; +typedef VkFlags VkQueryPoolCreateFlags; + +typedef enum VkQueryPipelineStatisticFlagBits { + VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0x00000001, + VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT = 0x00000002, + VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT = 0x00000004, + VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT = 0x00000008, + VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT = 0x00000010, + VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT = 0x00000020, + VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT = 0x00000040, + VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 0x00000080, + VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100, + VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200, + VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400, + VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueryPipelineStatisticFlagBits; +typedef VkFlags VkQueryPipelineStatisticFlags; + +typedef enum VkQueryResultFlagBits { + VK_QUERY_RESULT_64_BIT = 0x00000001, + VK_QUERY_RESULT_WAIT_BIT = 0x00000002, + VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004, + VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008, + VK_QUERY_RESULT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueryResultFlagBits; +typedef VkFlags VkQueryResultFlags; + +typedef enum VkBufferCreateFlagBits { + VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0x00000001, + VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, + VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004, + VK_BUFFER_CREATE_PROTECTED_BIT = 0x00000008, + VK_BUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkBufferCreateFlagBits; +typedef VkFlags VkBufferCreateFlags; + +typedef enum VkBufferUsageFlagBits { + VK_BUFFER_USAGE_TRANSFER_SRC_BIT = 0x00000001, + VK_BUFFER_USAGE_TRANSFER_DST_BIT = 0x00000002, + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004, + VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0x00000008, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0x00000010, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 0x00000020, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080, + VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100, + VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkBufferUsageFlagBits; +typedef VkFlags VkBufferUsageFlags; +typedef VkFlags VkBufferViewCreateFlags; +typedef VkFlags VkImageViewCreateFlags; +typedef VkFlags VkShaderModuleCreateFlags; +typedef VkFlags VkPipelineCacheCreateFlags; + +typedef enum VkPipelineCreateFlagBits { + VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001, + VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002, + VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, + VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, + VK_PIPELINE_CREATE_DISPATCH_BASE = 0x00000010, + VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT, + VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE, + VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCreateFlagBits; +typedef VkFlags VkPipelineCreateFlags; +typedef VkFlags VkPipelineShaderStageCreateFlags; + +typedef enum VkShaderStageFlagBits { + VK_SHADER_STAGE_VERTEX_BIT = 0x00000001, + VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002, + VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004, + VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008, + VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010, + VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020, + VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F, + VK_SHADER_STAGE_ALL = 0x7FFFFFFF, + VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkShaderStageFlagBits; +typedef VkFlags VkPipelineVertexInputStateCreateFlags; +typedef VkFlags VkPipelineInputAssemblyStateCreateFlags; +typedef VkFlags VkPipelineTessellationStateCreateFlags; +typedef VkFlags VkPipelineViewportStateCreateFlags; +typedef VkFlags VkPipelineRasterizationStateCreateFlags; + +typedef enum VkCullModeFlagBits { + VK_CULL_MODE_NONE = 0, + VK_CULL_MODE_FRONT_BIT = 0x00000001, + VK_CULL_MODE_BACK_BIT = 0x00000002, + VK_CULL_MODE_FRONT_AND_BACK = 0x00000003, + VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCullModeFlagBits; +typedef VkFlags VkCullModeFlags; +typedef VkFlags VkPipelineMultisampleStateCreateFlags; +typedef VkFlags VkPipelineDepthStencilStateCreateFlags; +typedef VkFlags VkPipelineColorBlendStateCreateFlags; + +typedef enum VkColorComponentFlagBits { + VK_COLOR_COMPONENT_R_BIT = 0x00000001, + VK_COLOR_COMPONENT_G_BIT = 0x00000002, + VK_COLOR_COMPONENT_B_BIT = 0x00000004, + VK_COLOR_COMPONENT_A_BIT = 0x00000008, + VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkColorComponentFlagBits; +typedef VkFlags VkColorComponentFlags; +typedef VkFlags VkPipelineDynamicStateCreateFlags; +typedef VkFlags VkPipelineLayoutCreateFlags; +typedef VkFlags VkShaderStageFlags; +typedef VkFlags VkSamplerCreateFlags; + +typedef enum VkDescriptorSetLayoutCreateFlagBits { + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorSetLayoutCreateFlagBits; +typedef VkFlags VkDescriptorSetLayoutCreateFlags; + +typedef enum VkDescriptorPoolCreateFlagBits { + VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001, + VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorPoolCreateFlagBits; +typedef VkFlags VkDescriptorPoolCreateFlags; +typedef VkFlags VkDescriptorPoolResetFlags; +typedef VkFlags VkFramebufferCreateFlags; +typedef VkFlags VkRenderPassCreateFlags; + +typedef enum VkAttachmentDescriptionFlagBits { + VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001, + VK_ATTACHMENT_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkAttachmentDescriptionFlagBits; +typedef VkFlags VkAttachmentDescriptionFlags; + +typedef enum VkSubpassDescriptionFlagBits { + VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001, + VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002, + VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSubpassDescriptionFlagBits; +typedef VkFlags VkSubpassDescriptionFlags; + +typedef enum VkAccessFlagBits { + VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001, + VK_ACCESS_INDEX_READ_BIT = 0x00000002, + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004, + VK_ACCESS_UNIFORM_READ_BIT = 0x00000008, + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010, + VK_ACCESS_SHADER_READ_BIT = 0x00000020, + VK_ACCESS_SHADER_WRITE_BIT = 0x00000040, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400, + VK_ACCESS_TRANSFER_READ_BIT = 0x00000800, + VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000, + VK_ACCESS_HOST_READ_BIT = 0x00002000, + VK_ACCESS_HOST_WRITE_BIT = 0x00004000, + VK_ACCESS_MEMORY_READ_BIT = 0x00008000, + VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, + VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000, + VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000, + VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, + VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkAccessFlagBits; +typedef VkFlags VkAccessFlags; + +typedef enum VkDependencyFlagBits { + VK_DEPENDENCY_BY_REGION_BIT = 0x00000001, + VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004, + VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002, + VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR = VK_DEPENDENCY_VIEW_LOCAL_BIT, + VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR = VK_DEPENDENCY_DEVICE_GROUP_BIT, + VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDependencyFlagBits; +typedef VkFlags VkDependencyFlags; + +typedef enum VkCommandPoolCreateFlagBits { + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001, + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002, + VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004, + VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandPoolCreateFlagBits; +typedef VkFlags VkCommandPoolCreateFlags; + +typedef enum VkCommandPoolResetFlagBits { + VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001, + VK_COMMAND_POOL_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandPoolResetFlagBits; +typedef VkFlags VkCommandPoolResetFlags; + +typedef enum VkCommandBufferUsageFlagBits { + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001, + VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002, + VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004, + VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandBufferUsageFlagBits; +typedef VkFlags VkCommandBufferUsageFlags; + +typedef enum VkQueryControlFlagBits { + VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001, + VK_QUERY_CONTROL_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueryControlFlagBits; +typedef VkFlags VkQueryControlFlags; + +typedef enum VkCommandBufferResetFlagBits { + VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001, + VK_COMMAND_BUFFER_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandBufferResetFlagBits; +typedef VkFlags VkCommandBufferResetFlags; + +typedef enum VkStencilFaceFlagBits { + VK_STENCIL_FACE_FRONT_BIT = 0x00000001, + VK_STENCIL_FACE_BACK_BIT = 0x00000002, + VK_STENCIL_FRONT_AND_BACK = 0x00000003, + VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkStencilFaceFlagBits; +typedef VkFlags VkStencilFaceFlags; + +typedef struct VkApplicationInfo { + VkStructureType sType; + const void* pNext; + const char* pApplicationName; + uint32_t applicationVersion; + const char* pEngineName; + uint32_t engineVersion; + uint32_t apiVersion; +} VkApplicationInfo; + +typedef struct VkInstanceCreateInfo { + VkStructureType sType; + const void* pNext; + VkInstanceCreateFlags flags; + const VkApplicationInfo* pApplicationInfo; + uint32_t enabledLayerCount; + const char* const* ppEnabledLayerNames; + uint32_t enabledExtensionCount; + const char* const* ppEnabledExtensionNames; +} VkInstanceCreateInfo; + +typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)( + void* pUserData, + size_t size, + size_t alignment, + VkSystemAllocationScope allocationScope); + +typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)( + void* pUserData, + void* pOriginal, + size_t size, + size_t alignment, + VkSystemAllocationScope allocationScope); + +typedef void (VKAPI_PTR *PFN_vkFreeFunction)( + void* pUserData, + void* pMemory); + +typedef void (VKAPI_PTR *PFN_vkInternalAllocationNotification)( + void* pUserData, + size_t size, + VkInternalAllocationType allocationType, + VkSystemAllocationScope allocationScope); + +typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)( + void* pUserData, + size_t size, + VkInternalAllocationType allocationType, + VkSystemAllocationScope allocationScope); + +typedef struct VkAllocationCallbacks { + void* pUserData; + PFN_vkAllocationFunction pfnAllocation; + PFN_vkReallocationFunction pfnReallocation; + PFN_vkFreeFunction pfnFree; + PFN_vkInternalAllocationNotification pfnInternalAllocation; + PFN_vkInternalFreeNotification pfnInternalFree; +} VkAllocationCallbacks; + +typedef struct VkPhysicalDeviceFeatures { + VkBool32 robustBufferAccess; + VkBool32 fullDrawIndexUint32; + VkBool32 imageCubeArray; + VkBool32 independentBlend; + VkBool32 geometryShader; + VkBool32 tessellationShader; + VkBool32 sampleRateShading; + VkBool32 dualSrcBlend; + VkBool32 logicOp; + VkBool32 multiDrawIndirect; + VkBool32 drawIndirectFirstInstance; + VkBool32 depthClamp; + VkBool32 depthBiasClamp; + VkBool32 fillModeNonSolid; + VkBool32 depthBounds; + VkBool32 wideLines; + VkBool32 largePoints; + VkBool32 alphaToOne; + VkBool32 multiViewport; + VkBool32 samplerAnisotropy; + VkBool32 textureCompressionETC2; + VkBool32 textureCompressionASTC_LDR; + VkBool32 textureCompressionBC; + VkBool32 occlusionQueryPrecise; + VkBool32 pipelineStatisticsQuery; + VkBool32 vertexPipelineStoresAndAtomics; + VkBool32 fragmentStoresAndAtomics; + VkBool32 shaderTessellationAndGeometryPointSize; + VkBool32 shaderImageGatherExtended; + VkBool32 shaderStorageImageExtendedFormats; + VkBool32 shaderStorageImageMultisample; + VkBool32 shaderStorageImageReadWithoutFormat; + VkBool32 shaderStorageImageWriteWithoutFormat; + VkBool32 shaderUniformBufferArrayDynamicIndexing; + VkBool32 shaderSampledImageArrayDynamicIndexing; + VkBool32 shaderStorageBufferArrayDynamicIndexing; + VkBool32 shaderStorageImageArrayDynamicIndexing; + VkBool32 shaderClipDistance; + VkBool32 shaderCullDistance; + VkBool32 shaderFloat64; + VkBool32 shaderInt64; + VkBool32 shaderInt16; + VkBool32 shaderResourceResidency; + VkBool32 shaderResourceMinLod; + VkBool32 sparseBinding; + VkBool32 sparseResidencyBuffer; + VkBool32 sparseResidencyImage2D; + VkBool32 sparseResidencyImage3D; + VkBool32 sparseResidency2Samples; + VkBool32 sparseResidency4Samples; + VkBool32 sparseResidency8Samples; + VkBool32 sparseResidency16Samples; + VkBool32 sparseResidencyAliased; + VkBool32 variableMultisampleRate; + VkBool32 inheritedQueries; +} VkPhysicalDeviceFeatures; + +typedef struct VkFormatProperties { + VkFormatFeatureFlags linearTilingFeatures; + VkFormatFeatureFlags optimalTilingFeatures; + VkFormatFeatureFlags bufferFeatures; +} VkFormatProperties; + +typedef struct VkExtent3D { + uint32_t width; + uint32_t height; + uint32_t depth; +} VkExtent3D; + +typedef struct VkImageFormatProperties { + VkExtent3D maxExtent; + uint32_t maxMipLevels; + uint32_t maxArrayLayers; + VkSampleCountFlags sampleCounts; + VkDeviceSize maxResourceSize; +} VkImageFormatProperties; + +typedef struct VkPhysicalDeviceLimits { + uint32_t maxImageDimension1D; + uint32_t maxImageDimension2D; + uint32_t maxImageDimension3D; + uint32_t maxImageDimensionCube; + uint32_t maxImageArrayLayers; + uint32_t maxTexelBufferElements; + uint32_t maxUniformBufferRange; + uint32_t maxStorageBufferRange; + uint32_t maxPushConstantsSize; + uint32_t maxMemoryAllocationCount; + uint32_t maxSamplerAllocationCount; + VkDeviceSize bufferImageGranularity; + VkDeviceSize sparseAddressSpaceSize; + uint32_t maxBoundDescriptorSets; + uint32_t maxPerStageDescriptorSamplers; + uint32_t maxPerStageDescriptorUniformBuffers; + uint32_t maxPerStageDescriptorStorageBuffers; + uint32_t maxPerStageDescriptorSampledImages; + uint32_t maxPerStageDescriptorStorageImages; + uint32_t maxPerStageDescriptorInputAttachments; + uint32_t maxPerStageResources; + uint32_t maxDescriptorSetSamplers; + uint32_t maxDescriptorSetUniformBuffers; + uint32_t maxDescriptorSetUniformBuffersDynamic; + uint32_t maxDescriptorSetStorageBuffers; + uint32_t maxDescriptorSetStorageBuffersDynamic; + uint32_t maxDescriptorSetSampledImages; + uint32_t maxDescriptorSetStorageImages; + uint32_t maxDescriptorSetInputAttachments; + uint32_t maxVertexInputAttributes; + uint32_t maxVertexInputBindings; + uint32_t maxVertexInputAttributeOffset; + uint32_t maxVertexInputBindingStride; + uint32_t maxVertexOutputComponents; + uint32_t maxTessellationGenerationLevel; + uint32_t maxTessellationPatchSize; + uint32_t maxTessellationControlPerVertexInputComponents; + uint32_t maxTessellationControlPerVertexOutputComponents; + uint32_t maxTessellationControlPerPatchOutputComponents; + uint32_t maxTessellationControlTotalOutputComponents; + uint32_t maxTessellationEvaluationInputComponents; + uint32_t maxTessellationEvaluationOutputComponents; + uint32_t maxGeometryShaderInvocations; + uint32_t maxGeometryInputComponents; + uint32_t maxGeometryOutputComponents; + uint32_t maxGeometryOutputVertices; + uint32_t maxGeometryTotalOutputComponents; + uint32_t maxFragmentInputComponents; + uint32_t maxFragmentOutputAttachments; + uint32_t maxFragmentDualSrcAttachments; + uint32_t maxFragmentCombinedOutputResources; + uint32_t maxComputeSharedMemorySize; + uint32_t maxComputeWorkGroupCount[3]; + uint32_t maxComputeWorkGroupInvocations; + uint32_t maxComputeWorkGroupSize[3]; + uint32_t subPixelPrecisionBits; + uint32_t subTexelPrecisionBits; + uint32_t mipmapPrecisionBits; + uint32_t maxDrawIndexedIndexValue; + uint32_t maxDrawIndirectCount; + float maxSamplerLodBias; + float maxSamplerAnisotropy; + uint32_t maxViewports; + uint32_t maxViewportDimensions[2]; + float viewportBoundsRange[2]; + uint32_t viewportSubPixelBits; + size_t minMemoryMapAlignment; + VkDeviceSize minTexelBufferOffsetAlignment; + VkDeviceSize minUniformBufferOffsetAlignment; + VkDeviceSize minStorageBufferOffsetAlignment; + int32_t minTexelOffset; + uint32_t maxTexelOffset; + int32_t minTexelGatherOffset; + uint32_t maxTexelGatherOffset; + float minInterpolationOffset; + float maxInterpolationOffset; + uint32_t subPixelInterpolationOffsetBits; + uint32_t maxFramebufferWidth; + uint32_t maxFramebufferHeight; + uint32_t maxFramebufferLayers; + VkSampleCountFlags framebufferColorSampleCounts; + VkSampleCountFlags framebufferDepthSampleCounts; + VkSampleCountFlags framebufferStencilSampleCounts; + VkSampleCountFlags framebufferNoAttachmentsSampleCounts; + uint32_t maxColorAttachments; + VkSampleCountFlags sampledImageColorSampleCounts; + VkSampleCountFlags sampledImageIntegerSampleCounts; + VkSampleCountFlags sampledImageDepthSampleCounts; + VkSampleCountFlags sampledImageStencilSampleCounts; + VkSampleCountFlags storageImageSampleCounts; + uint32_t maxSampleMaskWords; + VkBool32 timestampComputeAndGraphics; + float timestampPeriod; + uint32_t maxClipDistances; + uint32_t maxCullDistances; + uint32_t maxCombinedClipAndCullDistances; + uint32_t discreteQueuePriorities; + float pointSizeRange[2]; + float lineWidthRange[2]; + float pointSizeGranularity; + float lineWidthGranularity; + VkBool32 strictLines; + VkBool32 standardSampleLocations; + VkDeviceSize optimalBufferCopyOffsetAlignment; + VkDeviceSize optimalBufferCopyRowPitchAlignment; + VkDeviceSize nonCoherentAtomSize; +} VkPhysicalDeviceLimits; + +typedef struct VkPhysicalDeviceSparseProperties { + VkBool32 residencyStandard2DBlockShape; + VkBool32 residencyStandard2DMultisampleBlockShape; + VkBool32 residencyStandard3DBlockShape; + VkBool32 residencyAlignedMipSize; + VkBool32 residencyNonResidentStrict; +} VkPhysicalDeviceSparseProperties; + +typedef struct VkPhysicalDeviceProperties { + uint32_t apiVersion; + uint32_t driverVersion; + uint32_t vendorID; + uint32_t deviceID; + VkPhysicalDeviceType deviceType; + char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; + uint8_t pipelineCacheUUID[VK_UUID_SIZE]; + VkPhysicalDeviceLimits limits; + VkPhysicalDeviceSparseProperties sparseProperties; +} VkPhysicalDeviceProperties; + +typedef struct VkQueueFamilyProperties { + VkQueueFlags queueFlags; + uint32_t queueCount; + uint32_t timestampValidBits; + VkExtent3D minImageTransferGranularity; +} VkQueueFamilyProperties; + +typedef struct VkMemoryType { + VkMemoryPropertyFlags propertyFlags; + uint32_t heapIndex; +} VkMemoryType; + +typedef struct VkMemoryHeap { + VkDeviceSize size; + VkMemoryHeapFlags flags; +} VkMemoryHeap; + +typedef struct VkPhysicalDeviceMemoryProperties { + uint32_t memoryTypeCount; + VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES]; + uint32_t memoryHeapCount; + VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS]; +} VkPhysicalDeviceMemoryProperties; + +typedef void (VKAPI_PTR *PFN_vkVoidFunction)(void); +typedef struct VkDeviceQueueCreateInfo { + VkStructureType sType; + const void* pNext; + VkDeviceQueueCreateFlags flags; + uint32_t queueFamilyIndex; + uint32_t queueCount; + const float* pQueuePriorities; +} VkDeviceQueueCreateInfo; + +typedef struct VkDeviceCreateInfo { + VkStructureType sType; + const void* pNext; + VkDeviceCreateFlags flags; + uint32_t queueCreateInfoCount; + const VkDeviceQueueCreateInfo* pQueueCreateInfos; + uint32_t enabledLayerCount; + const char* const* ppEnabledLayerNames; + uint32_t enabledExtensionCount; + const char* const* ppEnabledExtensionNames; + const VkPhysicalDeviceFeatures* pEnabledFeatures; +} VkDeviceCreateInfo; + +typedef struct VkExtensionProperties { + char extensionName[VK_MAX_EXTENSION_NAME_SIZE]; + uint32_t specVersion; +} VkExtensionProperties; + +typedef struct VkLayerProperties { + char layerName[VK_MAX_EXTENSION_NAME_SIZE]; + uint32_t specVersion; + uint32_t implementationVersion; + char description[VK_MAX_DESCRIPTION_SIZE]; +} VkLayerProperties; + +typedef struct VkSubmitInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const VkSemaphore* pWaitSemaphores; + const VkPipelineStageFlags* pWaitDstStageMask; + uint32_t commandBufferCount; + const VkCommandBuffer* pCommandBuffers; + uint32_t signalSemaphoreCount; + const VkSemaphore* pSignalSemaphores; +} VkSubmitInfo; + +typedef struct VkMemoryAllocateInfo { + VkStructureType sType; + const void* pNext; + VkDeviceSize allocationSize; + uint32_t memoryTypeIndex; +} VkMemoryAllocateInfo; + +typedef struct VkMappedMemoryRange { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkDeviceSize offset; + VkDeviceSize size; +} VkMappedMemoryRange; + +typedef struct VkMemoryRequirements { + VkDeviceSize size; + VkDeviceSize alignment; + uint32_t memoryTypeBits; +} VkMemoryRequirements; + +typedef struct VkSparseImageFormatProperties { + VkImageAspectFlags aspectMask; + VkExtent3D imageGranularity; + VkSparseImageFormatFlags flags; +} VkSparseImageFormatProperties; + +typedef struct VkSparseImageMemoryRequirements { + VkSparseImageFormatProperties formatProperties; + uint32_t imageMipTailFirstLod; + VkDeviceSize imageMipTailSize; + VkDeviceSize imageMipTailOffset; + VkDeviceSize imageMipTailStride; +} VkSparseImageMemoryRequirements; + +typedef struct VkSparseMemoryBind { + VkDeviceSize resourceOffset; + VkDeviceSize size; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + VkSparseMemoryBindFlags flags; +} VkSparseMemoryBind; + +typedef struct VkSparseBufferMemoryBindInfo { + VkBuffer buffer; + uint32_t bindCount; + const VkSparseMemoryBind* pBinds; +} VkSparseBufferMemoryBindInfo; + +typedef struct VkSparseImageOpaqueMemoryBindInfo { + VkImage image; + uint32_t bindCount; + const VkSparseMemoryBind* pBinds; +} VkSparseImageOpaqueMemoryBindInfo; + +typedef struct VkImageSubresource { + VkImageAspectFlags aspectMask; + uint32_t mipLevel; + uint32_t arrayLayer; +} VkImageSubresource; + +typedef struct VkOffset3D { + int32_t x; + int32_t y; + int32_t z; +} VkOffset3D; + +typedef struct VkSparseImageMemoryBind { + VkImageSubresource subresource; + VkOffset3D offset; + VkExtent3D extent; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + VkSparseMemoryBindFlags flags; +} VkSparseImageMemoryBind; + +typedef struct VkSparseImageMemoryBindInfo { + VkImage image; + uint32_t bindCount; + const VkSparseImageMemoryBind* pBinds; +} VkSparseImageMemoryBindInfo; + +typedef struct VkBindSparseInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const VkSemaphore* pWaitSemaphores; + uint32_t bufferBindCount; + const VkSparseBufferMemoryBindInfo* pBufferBinds; + uint32_t imageOpaqueBindCount; + const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds; + uint32_t imageBindCount; + const VkSparseImageMemoryBindInfo* pImageBinds; + uint32_t signalSemaphoreCount; + const VkSemaphore* pSignalSemaphores; +} VkBindSparseInfo; + +typedef struct VkFenceCreateInfo { + VkStructureType sType; + const void* pNext; + VkFenceCreateFlags flags; +} VkFenceCreateInfo; + +typedef struct VkSemaphoreCreateInfo { + VkStructureType sType; + const void* pNext; + VkSemaphoreCreateFlags flags; +} VkSemaphoreCreateInfo; + +typedef struct VkEventCreateInfo { + VkStructureType sType; + const void* pNext; + VkEventCreateFlags flags; +} VkEventCreateInfo; + +typedef struct VkQueryPoolCreateInfo { + VkStructureType sType; + const void* pNext; + VkQueryPoolCreateFlags flags; + VkQueryType queryType; + uint32_t queryCount; + VkQueryPipelineStatisticFlags pipelineStatistics; +} VkQueryPoolCreateInfo; + +typedef struct VkBufferCreateInfo { + VkStructureType sType; + const void* pNext; + VkBufferCreateFlags flags; + VkDeviceSize size; + VkBufferUsageFlags usage; + VkSharingMode sharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; +} VkBufferCreateInfo; + +typedef struct VkBufferViewCreateInfo { + VkStructureType sType; + const void* pNext; + VkBufferViewCreateFlags flags; + VkBuffer buffer; + VkFormat format; + VkDeviceSize offset; + VkDeviceSize range; +} VkBufferViewCreateInfo; + +typedef struct VkImageCreateInfo { + VkStructureType sType; + const void* pNext; + VkImageCreateFlags flags; + VkImageType imageType; + VkFormat format; + VkExtent3D extent; + uint32_t mipLevels; + uint32_t arrayLayers; + VkSampleCountFlagBits samples; + VkImageTiling tiling; + VkImageUsageFlags usage; + VkSharingMode sharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; + VkImageLayout initialLayout; +} VkImageCreateInfo; + +typedef struct VkSubresourceLayout { + VkDeviceSize offset; + VkDeviceSize size; + VkDeviceSize rowPitch; + VkDeviceSize arrayPitch; + VkDeviceSize depthPitch; +} VkSubresourceLayout; + +typedef struct VkComponentMapping { + VkComponentSwizzle r; + VkComponentSwizzle g; + VkComponentSwizzle b; + VkComponentSwizzle a; +} VkComponentMapping; + +typedef struct VkImageSubresourceRange { + VkImageAspectFlags aspectMask; + uint32_t baseMipLevel; + uint32_t levelCount; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkImageSubresourceRange; + +typedef struct VkImageViewCreateInfo { + VkStructureType sType; + const void* pNext; + VkImageViewCreateFlags flags; + VkImage image; + VkImageViewType viewType; + VkFormat format; + VkComponentMapping components; + VkImageSubresourceRange subresourceRange; +} VkImageViewCreateInfo; + +typedef struct VkShaderModuleCreateInfo { + VkStructureType sType; + const void* pNext; + VkShaderModuleCreateFlags flags; + size_t codeSize; + const uint32_t* pCode; +} VkShaderModuleCreateInfo; + +typedef struct VkPipelineCacheCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCacheCreateFlags flags; + size_t initialDataSize; + const void* pInitialData; +} VkPipelineCacheCreateInfo; + +typedef struct VkSpecializationMapEntry { + uint32_t constantID; + uint32_t offset; + size_t size; +} VkSpecializationMapEntry; + +typedef struct VkSpecializationInfo { + uint32_t mapEntryCount; + const VkSpecializationMapEntry* pMapEntries; + size_t dataSize; + const void* pData; +} VkSpecializationInfo; + +typedef struct VkPipelineShaderStageCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineShaderStageCreateFlags flags; + VkShaderStageFlagBits stage; + VkShaderModule module; + const char* pName; + const VkSpecializationInfo* pSpecializationInfo; +} VkPipelineShaderStageCreateInfo; + +typedef struct VkVertexInputBindingDescription { + uint32_t binding; + uint32_t stride; + VkVertexInputRate inputRate; +} VkVertexInputBindingDescription; + +typedef struct VkVertexInputAttributeDescription { + uint32_t location; + uint32_t binding; + VkFormat format; + uint32_t offset; +} VkVertexInputAttributeDescription; + +typedef struct VkPipelineVertexInputStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineVertexInputStateCreateFlags flags; + uint32_t vertexBindingDescriptionCount; + const VkVertexInputBindingDescription* pVertexBindingDescriptions; + uint32_t vertexAttributeDescriptionCount; + const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; +} VkPipelineVertexInputStateCreateInfo; + +typedef struct VkPipelineInputAssemblyStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineInputAssemblyStateCreateFlags flags; + VkPrimitiveTopology topology; + VkBool32 primitiveRestartEnable; +} VkPipelineInputAssemblyStateCreateInfo; + +typedef struct VkPipelineTessellationStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineTessellationStateCreateFlags flags; + uint32_t patchControlPoints; +} VkPipelineTessellationStateCreateInfo; + +typedef struct VkViewport { + float x; + float y; + float width; + float height; + float minDepth; + float maxDepth; +} VkViewport; + +typedef struct VkOffset2D { + int32_t x; + int32_t y; +} VkOffset2D; + +typedef struct VkExtent2D { + uint32_t width; + uint32_t height; +} VkExtent2D; + +typedef struct VkRect2D { + VkOffset2D offset; + VkExtent2D extent; +} VkRect2D; + +typedef struct VkPipelineViewportStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineViewportStateCreateFlags flags; + uint32_t viewportCount; + const VkViewport* pViewports; + uint32_t scissorCount; + const VkRect2D* pScissors; +} VkPipelineViewportStateCreateInfo; + +typedef struct VkPipelineRasterizationStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationStateCreateFlags flags; + VkBool32 depthClampEnable; + VkBool32 rasterizerDiscardEnable; + VkPolygonMode polygonMode; + VkCullModeFlags cullMode; + VkFrontFace frontFace; + VkBool32 depthBiasEnable; + float depthBiasConstantFactor; + float depthBiasClamp; + float depthBiasSlopeFactor; + float lineWidth; +} VkPipelineRasterizationStateCreateInfo; + +typedef struct VkPipelineMultisampleStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineMultisampleStateCreateFlags flags; + VkSampleCountFlagBits rasterizationSamples; + VkBool32 sampleShadingEnable; + float minSampleShading; + const VkSampleMask* pSampleMask; + VkBool32 alphaToCoverageEnable; + VkBool32 alphaToOneEnable; +} VkPipelineMultisampleStateCreateInfo; + +typedef struct VkStencilOpState { + VkStencilOp failOp; + VkStencilOp passOp; + VkStencilOp depthFailOp; + VkCompareOp compareOp; + uint32_t compareMask; + uint32_t writeMask; + uint32_t reference; +} VkStencilOpState; + +typedef struct VkPipelineDepthStencilStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineDepthStencilStateCreateFlags flags; + VkBool32 depthTestEnable; + VkBool32 depthWriteEnable; + VkCompareOp depthCompareOp; + VkBool32 depthBoundsTestEnable; + VkBool32 stencilTestEnable; + VkStencilOpState front; + VkStencilOpState back; + float minDepthBounds; + float maxDepthBounds; +} VkPipelineDepthStencilStateCreateInfo; + +typedef struct VkPipelineColorBlendAttachmentState { + VkBool32 blendEnable; + VkBlendFactor srcColorBlendFactor; + VkBlendFactor dstColorBlendFactor; + VkBlendOp colorBlendOp; + VkBlendFactor srcAlphaBlendFactor; + VkBlendFactor dstAlphaBlendFactor; + VkBlendOp alphaBlendOp; + VkColorComponentFlags colorWriteMask; +} VkPipelineColorBlendAttachmentState; + +typedef struct VkPipelineColorBlendStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineColorBlendStateCreateFlags flags; + VkBool32 logicOpEnable; + VkLogicOp logicOp; + uint32_t attachmentCount; + const VkPipelineColorBlendAttachmentState* pAttachments; + float blendConstants[4]; +} VkPipelineColorBlendStateCreateInfo; + +typedef struct VkPipelineDynamicStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineDynamicStateCreateFlags flags; + uint32_t dynamicStateCount; + const VkDynamicState* pDynamicStates; +} VkPipelineDynamicStateCreateInfo; + +typedef struct VkGraphicsPipelineCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + const VkPipelineTessellationStateCreateInfo* pTessellationState; + const VkPipelineViewportStateCreateInfo* pViewportState; + const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + const VkPipelineDynamicStateCreateInfo* pDynamicState; + VkPipelineLayout layout; + VkRenderPass renderPass; + uint32_t subpass; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkGraphicsPipelineCreateInfo; + +typedef struct VkComputePipelineCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + VkPipelineShaderStageCreateInfo stage; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkComputePipelineCreateInfo; + +typedef struct VkPushConstantRange { + VkShaderStageFlags stageFlags; + uint32_t offset; + uint32_t size; +} VkPushConstantRange; + +typedef struct VkPipelineLayoutCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineLayoutCreateFlags flags; + uint32_t setLayoutCount; + const VkDescriptorSetLayout* pSetLayouts; + uint32_t pushConstantRangeCount; + const VkPushConstantRange* pPushConstantRanges; +} VkPipelineLayoutCreateInfo; + +typedef struct VkSamplerCreateInfo { + VkStructureType sType; + const void* pNext; + VkSamplerCreateFlags flags; + VkFilter magFilter; + VkFilter minFilter; + VkSamplerMipmapMode mipmapMode; + VkSamplerAddressMode addressModeU; + VkSamplerAddressMode addressModeV; + VkSamplerAddressMode addressModeW; + float mipLodBias; + VkBool32 anisotropyEnable; + float maxAnisotropy; + VkBool32 compareEnable; + VkCompareOp compareOp; + float minLod; + float maxLod; + VkBorderColor borderColor; + VkBool32 unnormalizedCoordinates; +} VkSamplerCreateInfo; + +typedef struct VkDescriptorSetLayoutBinding { + uint32_t binding; + VkDescriptorType descriptorType; + uint32_t descriptorCount; + VkShaderStageFlags stageFlags; + const VkSampler* pImmutableSamplers; +} VkDescriptorSetLayoutBinding; + +typedef struct VkDescriptorSetLayoutCreateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorSetLayoutCreateFlags flags; + uint32_t bindingCount; + const VkDescriptorSetLayoutBinding* pBindings; +} VkDescriptorSetLayoutCreateInfo; + +typedef struct VkDescriptorPoolSize { + VkDescriptorType type; + uint32_t descriptorCount; +} VkDescriptorPoolSize; + +typedef struct VkDescriptorPoolCreateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorPoolCreateFlags flags; + uint32_t maxSets; + uint32_t poolSizeCount; + const VkDescriptorPoolSize* pPoolSizes; +} VkDescriptorPoolCreateInfo; + +typedef struct VkDescriptorSetAllocateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorPool descriptorPool; + uint32_t descriptorSetCount; + const VkDescriptorSetLayout* pSetLayouts; +} VkDescriptorSetAllocateInfo; + +typedef struct VkDescriptorImageInfo { + VkSampler sampler; + VkImageView imageView; + VkImageLayout imageLayout; +} VkDescriptorImageInfo; + +typedef struct VkDescriptorBufferInfo { + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize range; +} VkDescriptorBufferInfo; + +typedef struct VkWriteDescriptorSet { + VkStructureType sType; + const void* pNext; + VkDescriptorSet dstSet; + uint32_t dstBinding; + uint32_t dstArrayElement; + uint32_t descriptorCount; + VkDescriptorType descriptorType; + const VkDescriptorImageInfo* pImageInfo; + const VkDescriptorBufferInfo* pBufferInfo; + const VkBufferView* pTexelBufferView; +} VkWriteDescriptorSet; + +typedef struct VkCopyDescriptorSet { + VkStructureType sType; + const void* pNext; + VkDescriptorSet srcSet; + uint32_t srcBinding; + uint32_t srcArrayElement; + VkDescriptorSet dstSet; + uint32_t dstBinding; + uint32_t dstArrayElement; + uint32_t descriptorCount; +} VkCopyDescriptorSet; + +typedef struct VkFramebufferCreateInfo { + VkStructureType sType; + const void* pNext; + VkFramebufferCreateFlags flags; + VkRenderPass renderPass; + uint32_t attachmentCount; + const VkImageView* pAttachments; + uint32_t width; + uint32_t height; + uint32_t layers; +} VkFramebufferCreateInfo; + +typedef struct VkAttachmentDescription { + VkAttachmentDescriptionFlags flags; + VkFormat format; + VkSampleCountFlagBits samples; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkAttachmentLoadOp stencilLoadOp; + VkAttachmentStoreOp stencilStoreOp; + VkImageLayout initialLayout; + VkImageLayout finalLayout; +} VkAttachmentDescription; + +typedef struct VkAttachmentReference { + uint32_t attachment; + VkImageLayout layout; +} VkAttachmentReference; + +typedef struct VkSubpassDescription { + VkSubpassDescriptionFlags flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t inputAttachmentCount; + const VkAttachmentReference* pInputAttachments; + uint32_t colorAttachmentCount; + const VkAttachmentReference* pColorAttachments; + const VkAttachmentReference* pResolveAttachments; + const VkAttachmentReference* pDepthStencilAttachment; + uint32_t preserveAttachmentCount; + const uint32_t* pPreserveAttachments; +} VkSubpassDescription; + +typedef struct VkSubpassDependency { + uint32_t srcSubpass; + uint32_t dstSubpass; + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkDependencyFlags dependencyFlags; +} VkSubpassDependency; + +typedef struct VkRenderPassCreateInfo { + VkStructureType sType; + const void* pNext; + VkRenderPassCreateFlags flags; + uint32_t attachmentCount; + const VkAttachmentDescription* pAttachments; + uint32_t subpassCount; + const VkSubpassDescription* pSubpasses; + uint32_t dependencyCount; + const VkSubpassDependency* pDependencies; +} VkRenderPassCreateInfo; + +typedef struct VkCommandPoolCreateInfo { + VkStructureType sType; + const void* pNext; + VkCommandPoolCreateFlags flags; + uint32_t queueFamilyIndex; +} VkCommandPoolCreateInfo; + +typedef struct VkCommandBufferAllocateInfo { + VkStructureType sType; + const void* pNext; + VkCommandPool commandPool; + VkCommandBufferLevel level; + uint32_t commandBufferCount; +} VkCommandBufferAllocateInfo; + +typedef struct VkCommandBufferInheritanceInfo { + VkStructureType sType; + const void* pNext; + VkRenderPass renderPass; + uint32_t subpass; + VkFramebuffer framebuffer; + VkBool32 occlusionQueryEnable; + VkQueryControlFlags queryFlags; + VkQueryPipelineStatisticFlags pipelineStatistics; +} VkCommandBufferInheritanceInfo; + +typedef struct VkCommandBufferBeginInfo { + VkStructureType sType; + const void* pNext; + VkCommandBufferUsageFlags flags; + const VkCommandBufferInheritanceInfo* pInheritanceInfo; +} VkCommandBufferBeginInfo; + +typedef struct VkBufferCopy { + VkDeviceSize srcOffset; + VkDeviceSize dstOffset; + VkDeviceSize size; +} VkBufferCopy; + +typedef struct VkImageSubresourceLayers { + VkImageAspectFlags aspectMask; + uint32_t mipLevel; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkImageSubresourceLayers; + +typedef struct VkImageCopy { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy; + +typedef struct VkImageBlit { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffsets[2]; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffsets[2]; +} VkImageBlit; + +typedef struct VkBufferImageCopy { + VkDeviceSize bufferOffset; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkBufferImageCopy; + +typedef union VkClearColorValue { + float float32[4]; + int32_t int32[4]; + uint32_t uint32[4]; +} VkClearColorValue; + +typedef struct VkClearDepthStencilValue { + float depth; + uint32_t stencil; +} VkClearDepthStencilValue; + +typedef union VkClearValue { + VkClearColorValue color; + VkClearDepthStencilValue depthStencil; +} VkClearValue; + +typedef struct VkClearAttachment { + VkImageAspectFlags aspectMask; + uint32_t colorAttachment; + VkClearValue clearValue; +} VkClearAttachment; + +typedef struct VkClearRect { + VkRect2D rect; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkClearRect; + +typedef struct VkImageResolve { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageResolve; + +typedef struct VkMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; +} VkMemoryBarrier; + +typedef struct VkBufferMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier; + +typedef struct VkImageMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier; + +typedef struct VkRenderPassBeginInfo { + VkStructureType sType; + const void* pNext; + VkRenderPass renderPass; + VkFramebuffer framebuffer; + VkRect2D renderArea; + uint32_t clearValueCount; + const VkClearValue* pClearValues; +} VkRenderPassBeginInfo; + +typedef struct VkDispatchIndirectCommand { + uint32_t x; + uint32_t y; + uint32_t z; +} VkDispatchIndirectCommand; + +typedef struct VkDrawIndexedIndirectCommand { + uint32_t indexCount; + uint32_t instanceCount; + uint32_t firstIndex; + int32_t vertexOffset; + uint32_t firstInstance; +} VkDrawIndexedIndirectCommand; + +typedef struct VkDrawIndirectCommand { + uint32_t vertexCount; + uint32_t instanceCount; + uint32_t firstVertex; + uint32_t firstInstance; +} VkDrawIndirectCommand; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateInstance)(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance); +typedef void (VKAPI_PTR *PFN_vkDestroyInstance)(VkInstance instance, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDevices)(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties); +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetInstanceProcAddr)(VkInstance instance, const char* pName); +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetDeviceProcAddr)(VkDevice device, const char* pName); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDevice)(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice); +typedef void (VKAPI_PTR *PFN_vkDestroyDevice)(VkDevice device, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceExtensionProperties)(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceExtensionProperties)(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceLayerProperties)(uint32_t* pPropertyCount, VkLayerProperties* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceLayerProperties)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue)(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence); +typedef VkResult (VKAPI_PTR *PFN_vkQueueWaitIdle)(VkQueue queue); +typedef VkResult (VKAPI_PTR *PFN_vkDeviceWaitIdle)(VkDevice device); +typedef VkResult (VKAPI_PTR *PFN_vkAllocateMemory)(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory); +typedef void (VKAPI_PTR *PFN_vkFreeMemory)(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkMapMemory)(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData); +typedef void (VKAPI_PTR *PFN_vkUnmapMemory)(VkDevice device, VkDeviceMemory memory); +typedef VkResult (VKAPI_PTR *PFN_vkFlushMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges); +typedef VkResult (VKAPI_PTR *PFN_vkInvalidateMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges); +typedef void (VKAPI_PTR *PFN_vkGetDeviceMemoryCommitment)(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes); +typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory)(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset); +typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory)(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset); +typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements)(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements)(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements)(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkQueueBindSparse)(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence); +typedef VkResult (VKAPI_PTR *PFN_vkCreateFence)(VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +typedef void (VKAPI_PTR *PFN_vkDestroyFence)(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkResetFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences); +typedef VkResult (VKAPI_PTR *PFN_vkGetFenceStatus)(VkDevice device, VkFence fence); +typedef VkResult (VKAPI_PTR *PFN_vkWaitForFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout); +typedef VkResult (VKAPI_PTR *PFN_vkCreateSemaphore)(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore); +typedef void (VKAPI_PTR *PFN_vkDestroySemaphore)(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateEvent)(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent); +typedef void (VKAPI_PTR *PFN_vkDestroyEvent)(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetEventStatus)(VkDevice device, VkEvent event); +typedef VkResult (VKAPI_PTR *PFN_vkSetEvent)(VkDevice device, VkEvent event); +typedef VkResult (VKAPI_PTR *PFN_vkResetEvent)(VkDevice device, VkEvent event); +typedef VkResult (VKAPI_PTR *PFN_vkCreateQueryPool)(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool); +typedef void (VKAPI_PTR *PFN_vkDestroyQueryPool)(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetQueryPoolResults)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags); +typedef VkResult (VKAPI_PTR *PFN_vkCreateBuffer)(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer); +typedef void (VKAPI_PTR *PFN_vkDestroyBuffer)(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView); +typedef void (VKAPI_PTR *PFN_vkDestroyBufferView)(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateImage)(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage); +typedef void (VKAPI_PTR *PFN_vkDestroyImage)(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout)(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout); +typedef VkResult (VKAPI_PTR *PFN_vkCreateImageView)(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView); +typedef void (VKAPI_PTR *PFN_vkDestroyImageView)(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateShaderModule)(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule); +typedef void (VKAPI_PTR *PFN_vkDestroyShaderModule)(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineCache)(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache); +typedef void (VKAPI_PTR *PFN_vkDestroyPipelineCache)(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineCacheData)(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkMergePipelineCaches)(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches); +typedef VkResult (VKAPI_PTR *PFN_vkCreateGraphicsPipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkCreateComputePipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef void (VKAPI_PTR *PFN_vkDestroyPipeline)(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineLayout)(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyPipelineLayout)(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateSampler)(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler); +typedef void (VKAPI_PTR *PFN_vkDestroySampler)(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorSetLayout)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorSetLayout)(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorPool)(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkResetDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags); +typedef VkResult (VKAPI_PTR *PFN_vkAllocateDescriptorSets)(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets); +typedef VkResult (VKAPI_PTR *PFN_vkFreeDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets); +typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSets)(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies); +typedef VkResult (VKAPI_PTR *PFN_vkCreateFramebuffer)(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer); +typedef void (VKAPI_PTR *PFN_vkDestroyFramebuffer)(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass)(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); +typedef void (VKAPI_PTR *PFN_vkDestroyRenderPass)(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetRenderAreaGranularity)(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCommandPool)(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool); +typedef void (VKAPI_PTR *PFN_vkDestroyCommandPool)(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkResetCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags); +typedef VkResult (VKAPI_PTR *PFN_vkAllocateCommandBuffers)(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers); +typedef void (VKAPI_PTR *PFN_vkFreeCommandBuffers)(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); +typedef VkResult (VKAPI_PTR *PFN_vkBeginCommandBuffer)(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo); +typedef VkResult (VKAPI_PTR *PFN_vkEndCommandBuffer)(VkCommandBuffer commandBuffer); +typedef VkResult (VKAPI_PTR *PFN_vkResetCommandBuffer)(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags); +typedef void (VKAPI_PTR *PFN_vkCmdBindPipeline)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewport)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports); +typedef void (VKAPI_PTR *PFN_vkCmdSetScissor)(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors); +typedef void (VKAPI_PTR *PFN_vkCmdSetLineWidth)(VkCommandBuffer commandBuffer, float lineWidth); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBias)(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor); +typedef void (VKAPI_PTR *PFN_vkCmdSetBlendConstants)(VkCommandBuffer commandBuffer, const float blendConstants[4]); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBounds)(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilCompareMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilWriteMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilReference)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference); +typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdDraw)(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexed)(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdBlitImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdUpdateBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdFillBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data); +typedef void (VKAPI_PTR *PFN_vkCmdClearColorImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges); +typedef void (VKAPI_PTR *PFN_vkCmdClearDepthStencilImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges); +typedef void (VKAPI_PTR *PFN_vkCmdClearAttachments)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects); +typedef void (VKAPI_PTR *PFN_vkCmdResolveImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier)(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); +typedef void (VKAPI_PTR *PFN_vkCmdBeginQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags); +typedef void (VKAPI_PTR *PFN_vkCmdEndQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query); +typedef void (VKAPI_PTR *PFN_vkCmdResetQueryPool)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query); +typedef void (VKAPI_PTR *PFN_vkCmdCopyQueryPoolResults)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags); +typedef void (VKAPI_PTR *PFN_vkCmdPushConstants)(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents); +typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass)(VkCommandBuffer commandBuffer, VkSubpassContents contents); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdExecuteCommands)(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance( + const VkInstanceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkInstance* pInstance); + +VKAPI_ATTR void VKAPI_CALL vkDestroyInstance( + VkInstance instance, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices( + VkInstance instance, + uint32_t* pPhysicalDeviceCount, + VkPhysicalDevice* pPhysicalDevices); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures* pFeatures); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkFormatProperties* pFormatProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags, + VkImageFormatProperties* pImageFormatProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceProperties* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties( + VkPhysicalDevice physicalDevice, + uint32_t* pQueueFamilyPropertyCount, + VkQueueFamilyProperties* pQueueFamilyProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties* pMemoryProperties); + +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr( + VkInstance instance, + const char* pName); + +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr( + VkDevice device, + const char* pName); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice( + VkPhysicalDevice physicalDevice, + const VkDeviceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDevice* pDevice); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDevice( + VkDevice device, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties( + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties( + VkPhysicalDevice physicalDevice, + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties( + uint32_t* pPropertyCount, + VkLayerProperties* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkLayerProperties* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue( + VkDevice device, + uint32_t queueFamilyIndex, + uint32_t queueIndex, + VkQueue* pQueue); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo* pSubmits, + VkFence fence); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle( + VkQueue queue); + +VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle( + VkDevice device); + +VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory( + VkDevice device, + const VkMemoryAllocateInfo* pAllocateInfo, + const VkAllocationCallbacks* pAllocator, + VkDeviceMemory* pMemory); + +VKAPI_ATTR void VKAPI_CALL vkFreeMemory( + VkDevice device, + VkDeviceMemory memory, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory( + VkDevice device, + VkDeviceMemory memory, + VkDeviceSize offset, + VkDeviceSize size, + VkMemoryMapFlags flags, + void** ppData); + +VKAPI_ATTR void VKAPI_CALL vkUnmapMemory( + VkDevice device, + VkDeviceMemory memory); + +VKAPI_ATTR VkResult VKAPI_CALL vkFlushMappedMemoryRanges( + VkDevice device, + uint32_t memoryRangeCount, + const VkMappedMemoryRange* pMemoryRanges); + +VKAPI_ATTR VkResult VKAPI_CALL vkInvalidateMappedMemoryRanges( + VkDevice device, + uint32_t memoryRangeCount, + const VkMappedMemoryRange* pMemoryRanges); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceMemoryCommitment( + VkDevice device, + VkDeviceMemory memory, + VkDeviceSize* pCommittedMemoryInBytes); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory( + VkDevice device, + VkBuffer buffer, + VkDeviceMemory memory, + VkDeviceSize memoryOffset); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory( + VkDevice device, + VkImage image, + VkDeviceMemory memory, + VkDeviceSize memoryOffset); + +VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements( + VkDevice device, + VkBuffer buffer, + VkMemoryRequirements* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements( + VkDevice device, + VkImage image, + VkMemoryRequirements* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements( + VkDevice device, + VkImage image, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements* pSparseMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkImageType type, + VkSampleCountFlagBits samples, + VkImageUsageFlags usage, + VkImageTiling tiling, + uint32_t* pPropertyCount, + VkSparseImageFormatProperties* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueBindSparse( + VkQueue queue, + uint32_t bindInfoCount, + const VkBindSparseInfo* pBindInfo, + VkFence fence); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateFence( + VkDevice device, + const VkFenceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkFence* pFence); + +VKAPI_ATTR void VKAPI_CALL vkDestroyFence( + VkDevice device, + VkFence fence, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetFences( + VkDevice device, + uint32_t fenceCount, + const VkFence* pFences); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus( + VkDevice device, + VkFence fence); + +VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences( + VkDevice device, + uint32_t fenceCount, + const VkFence* pFences, + VkBool32 waitAll, + uint64_t timeout); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore( + VkDevice device, + const VkSemaphoreCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSemaphore* pSemaphore); + +VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore( + VkDevice device, + VkSemaphore semaphore, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent( + VkDevice device, + const VkEventCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkEvent* pEvent); + +VKAPI_ATTR void VKAPI_CALL vkDestroyEvent( + VkDevice device, + VkEvent event, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus( + VkDevice device, + VkEvent event); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent( + VkDevice device, + VkEvent event); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent( + VkDevice device, + VkEvent event); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateQueryPool( + VkDevice device, + const VkQueryPoolCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkQueryPool* pQueryPool); + +VKAPI_ATTR void VKAPI_CALL vkDestroyQueryPool( + VkDevice device, + VkQueryPool queryPool, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults( + VkDevice device, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount, + size_t dataSize, + void* pData, + VkDeviceSize stride, + VkQueryResultFlags flags); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateBuffer( + VkDevice device, + const VkBufferCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkBuffer* pBuffer); + +VKAPI_ATTR void VKAPI_CALL vkDestroyBuffer( + VkDevice device, + VkBuffer buffer, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView( + VkDevice device, + const VkBufferViewCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkBufferView* pView); + +VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView( + VkDevice device, + VkBufferView bufferView, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage( + VkDevice device, + const VkImageCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkImage* pImage); + +VKAPI_ATTR void VKAPI_CALL vkDestroyImage( + VkDevice device, + VkImage image, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout( + VkDevice device, + VkImage image, + const VkImageSubresource* pSubresource, + VkSubresourceLayout* pLayout); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView( + VkDevice device, + const VkImageViewCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkImageView* pView); + +VKAPI_ATTR void VKAPI_CALL vkDestroyImageView( + VkDevice device, + VkImageView imageView, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule( + VkDevice device, + const VkShaderModuleCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkShaderModule* pShaderModule); + +VKAPI_ATTR void VKAPI_CALL vkDestroyShaderModule( + VkDevice device, + VkShaderModule shaderModule, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache( + VkDevice device, + const VkPipelineCacheCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPipelineCache* pPipelineCache); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineCache( + VkDevice device, + VkPipelineCache pipelineCache, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineCacheData( + VkDevice device, + VkPipelineCache pipelineCache, + size_t* pDataSize, + void* pData); + +VKAPI_ATTR VkResult VKAPI_CALL vkMergePipelineCaches( + VkDevice device, + VkPipelineCache dstCache, + uint32_t srcCacheCount, + const VkPipelineCache* pSrcCaches); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkGraphicsPipelineCreateInfo* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateComputePipelines( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkComputePipelineCreateInfo* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPipeline( + VkDevice device, + VkPipeline pipeline, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineLayout( + VkDevice device, + const VkPipelineLayoutCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPipelineLayout* pPipelineLayout); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineLayout( + VkDevice device, + VkPipelineLayout pipelineLayout, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler( + VkDevice device, + const VkSamplerCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSampler* pSampler); + +VKAPI_ATTR void VKAPI_CALL vkDestroySampler( + VkDevice device, + VkSampler sampler, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorSetLayout( + VkDevice device, + const VkDescriptorSetLayoutCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorSetLayout* pSetLayout); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorSetLayout( + VkDevice device, + VkDescriptorSetLayout descriptorSetLayout, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorPool( + VkDevice device, + const VkDescriptorPoolCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorPool* pDescriptorPool); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorPool( + VkDevice device, + VkDescriptorPool descriptorPool, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetDescriptorPool( + VkDevice device, + VkDescriptorPool descriptorPool, + VkDescriptorPoolResetFlags flags); + +VKAPI_ATTR VkResult VKAPI_CALL vkAllocateDescriptorSets( + VkDevice device, + const VkDescriptorSetAllocateInfo* pAllocateInfo, + VkDescriptorSet* pDescriptorSets); + +VKAPI_ATTR VkResult VKAPI_CALL vkFreeDescriptorSets( + VkDevice device, + VkDescriptorPool descriptorPool, + uint32_t descriptorSetCount, + const VkDescriptorSet* pDescriptorSets); + +VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSets( + VkDevice device, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites, + uint32_t descriptorCopyCount, + const VkCopyDescriptorSet* pDescriptorCopies); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer( + VkDevice device, + const VkFramebufferCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkFramebuffer* pFramebuffer); + +VKAPI_ATTR void VKAPI_CALL vkDestroyFramebuffer( + VkDevice device, + VkFramebuffer framebuffer, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass( + VkDevice device, + const VkRenderPassCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkRenderPass* pRenderPass); + +VKAPI_ATTR void VKAPI_CALL vkDestroyRenderPass( + VkDevice device, + VkRenderPass renderPass, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkGetRenderAreaGranularity( + VkDevice device, + VkRenderPass renderPass, + VkExtent2D* pGranularity); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool( + VkDevice device, + const VkCommandPoolCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCommandPool* pCommandPool); + +VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool( + VkDevice device, + VkCommandPool commandPool, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandPool( + VkDevice device, + VkCommandPool commandPool, + VkCommandPoolResetFlags flags); + +VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers( + VkDevice device, + const VkCommandBufferAllocateInfo* pAllocateInfo, + VkCommandBuffer* pCommandBuffers); + +VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers( + VkDevice device, + VkCommandPool commandPool, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers); + +VKAPI_ATTR VkResult VKAPI_CALL vkBeginCommandBuffer( + VkCommandBuffer commandBuffer, + const VkCommandBufferBeginInfo* pBeginInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer( + VkCommandBuffer commandBuffer, + VkCommandBufferResetFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindPipeline( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipeline pipeline); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewport( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewport* pViewports); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetScissor( + VkCommandBuffer commandBuffer, + uint32_t firstScissor, + uint32_t scissorCount, + const VkRect2D* pScissors); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineWidth( + VkCommandBuffer commandBuffer, + float lineWidth); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias( + VkCommandBuffer commandBuffer, + float depthBiasConstantFactor, + float depthBiasClamp, + float depthBiasSlopeFactor); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants( + VkCommandBuffer commandBuffer, + const float blendConstants[4]); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBounds( + VkCommandBuffer commandBuffer, + float minDepthBounds, + float maxDepthBounds); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilCompareMask( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t compareMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilWriteMask( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t writeMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilReference( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t reference); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t firstSet, + uint32_t descriptorSetCount, + const VkDescriptorSet* pDescriptorSets, + uint32_t dynamicOffsetCount, + const uint32_t* pDynamicOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkIndexType indexType); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdDraw( + VkCommandBuffer commandBuffer, + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t firstVertex, + uint32_t firstInstance); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexed( + VkCommandBuffer commandBuffer, + uint32_t indexCount, + uint32_t instanceCount, + uint32_t firstIndex, + int32_t vertexOffset, + uint32_t firstInstance); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirect( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatch( + VkCommandBuffer commandBuffer, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer( + VkCommandBuffer commandBuffer, + VkBuffer srcBuffer, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageBlit* pRegions, + VkFilter filter); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage( + VkCommandBuffer commandBuffer, + VkBuffer srcBuffer, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkBufferImageCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferImageCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer( + VkCommandBuffer commandBuffer, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize dataSize, + const void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer( + VkCommandBuffer commandBuffer, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize size, + uint32_t data); + +VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage( + VkCommandBuffer commandBuffer, + VkImage image, + VkImageLayout imageLayout, + const VkClearColorValue* pColor, + uint32_t rangeCount, + const VkImageSubresourceRange* pRanges); + +VKAPI_ATTR void VKAPI_CALL vkCmdClearDepthStencilImage( + VkCommandBuffer commandBuffer, + VkImage image, + VkImageLayout imageLayout, + const VkClearDepthStencilValue* pDepthStencil, + uint32_t rangeCount, + const VkImageSubresourceRange* pRanges); + +VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments( + VkCommandBuffer commandBuffer, + uint32_t attachmentCount, + const VkClearAttachment* pAttachments, + uint32_t rectCount, + const VkClearRect* pRects); + +VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageResolve* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + uint32_t memoryBarrierCount, + const VkMemoryBarrier* pMemoryBarriers, + uint32_t bufferMemoryBarrierCount, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + uint32_t imageMemoryBarrierCount, + const VkImageMemoryBarrier* pImageMemoryBarriers); + +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + VkDependencyFlags dependencyFlags, + uint32_t memoryBarrierCount, + const VkMemoryBarrier* pMemoryBarriers, + uint32_t bufferMemoryBarrierCount, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + uint32_t imageMemoryBarrierCount, + const VkImageMemoryBarrier* pImageMemoryBarriers); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginQuery( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + VkQueryControlFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetQueryPool( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp( + VkCommandBuffer commandBuffer, + VkPipelineStageFlagBits pipelineStage, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResults( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize stride, + VkQueryResultFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants( + VkCommandBuffer commandBuffer, + VkPipelineLayout layout, + VkShaderStageFlags stageFlags, + uint32_t offset, + uint32_t size, + const void* pValues); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass( + VkCommandBuffer commandBuffer, + const VkRenderPassBeginInfo* pRenderPassBegin, + VkSubpassContents contents); + +VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass( + VkCommandBuffer commandBuffer, + VkSubpassContents contents); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands( + VkCommandBuffer commandBuffer, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers); +#endif + +#define VK_VERSION_1_1 1 +// Vulkan 1.1 version number +#define VK_API_VERSION_1_1 VK_MAKE_VERSION(1, 1, 0)// Patch version should always be set to 0 + + +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversion) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate) + +#define VK_MAX_DEVICE_GROUP_SIZE 32 +#define VK_LUID_SIZE 8 +#define VK_QUEUE_FAMILY_EXTERNAL (~0U-1) + + +typedef enum VkPointClippingBehavior { + VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0, + VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1, + VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES, + VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY, + VK_POINT_CLIPPING_BEHAVIOR_BEGIN_RANGE = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES, + VK_POINT_CLIPPING_BEHAVIOR_END_RANGE = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY, + VK_POINT_CLIPPING_BEHAVIOR_RANGE_SIZE = (VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY - VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES + 1), + VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF +} VkPointClippingBehavior; + +typedef enum VkTessellationDomainOrigin { + VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0, + VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1, + VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, + VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT, + VK_TESSELLATION_DOMAIN_ORIGIN_BEGIN_RANGE = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, + VK_TESSELLATION_DOMAIN_ORIGIN_END_RANGE = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT, + VK_TESSELLATION_DOMAIN_ORIGIN_RANGE_SIZE = (VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT + 1), + VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM = 0x7FFFFFFF +} VkTessellationDomainOrigin; + +typedef enum VkSamplerYcbcrModelConversion { + VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY = 1, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 = 2, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 = 3, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_BEGIN_RANGE = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_END_RANGE = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_RANGE_SIZE = (VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY + 1), + VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM = 0x7FFFFFFF +} VkSamplerYcbcrModelConversion; + +typedef enum VkSamplerYcbcrRange { + VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0, + VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1, + VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_FULL, + VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, + VK_SAMPLER_YCBCR_RANGE_BEGIN_RANGE = VK_SAMPLER_YCBCR_RANGE_ITU_FULL, + VK_SAMPLER_YCBCR_RANGE_END_RANGE = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, + VK_SAMPLER_YCBCR_RANGE_RANGE_SIZE = (VK_SAMPLER_YCBCR_RANGE_ITU_NARROW - VK_SAMPLER_YCBCR_RANGE_ITU_FULL + 1), + VK_SAMPLER_YCBCR_RANGE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerYcbcrRange; + +typedef enum VkChromaLocation { + VK_CHROMA_LOCATION_COSITED_EVEN = 0, + VK_CHROMA_LOCATION_MIDPOINT = 1, + VK_CHROMA_LOCATION_COSITED_EVEN_KHR = VK_CHROMA_LOCATION_COSITED_EVEN, + VK_CHROMA_LOCATION_MIDPOINT_KHR = VK_CHROMA_LOCATION_MIDPOINT, + VK_CHROMA_LOCATION_BEGIN_RANGE = VK_CHROMA_LOCATION_COSITED_EVEN, + VK_CHROMA_LOCATION_END_RANGE = VK_CHROMA_LOCATION_MIDPOINT, + VK_CHROMA_LOCATION_RANGE_SIZE = (VK_CHROMA_LOCATION_MIDPOINT - VK_CHROMA_LOCATION_COSITED_EVEN + 1), + VK_CHROMA_LOCATION_MAX_ENUM = 0x7FFFFFFF +} VkChromaLocation; + +typedef enum VkDescriptorUpdateTemplateType { + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_END_RANGE = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET + 1), + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorUpdateTemplateType; + + +typedef enum VkSubgroupFeatureFlagBits { + VK_SUBGROUP_FEATURE_BASIC_BIT = 0x00000001, + VK_SUBGROUP_FEATURE_VOTE_BIT = 0x00000002, + VK_SUBGROUP_FEATURE_ARITHMETIC_BIT = 0x00000004, + VK_SUBGROUP_FEATURE_BALLOT_BIT = 0x00000008, + VK_SUBGROUP_FEATURE_SHUFFLE_BIT = 0x00000010, + VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 0x00000020, + VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 0x00000040, + VK_SUBGROUP_FEATURE_QUAD_BIT = 0x00000080, + VK_SUBGROUP_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSubgroupFeatureFlagBits; +typedef VkFlags VkSubgroupFeatureFlags; + +typedef enum VkPeerMemoryFeatureFlagBits { + VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 0x00000001, + VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 0x00000002, + VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 0x00000004, + VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 0x00000008, + VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT, + VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_DST_BIT, + VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT, + VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT, + VK_PEER_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPeerMemoryFeatureFlagBits; +typedef VkFlags VkPeerMemoryFeatureFlags; + +typedef enum VkMemoryAllocateFlagBits { + VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0x00000001, + VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT, + VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryAllocateFlagBits; +typedef VkFlags VkMemoryAllocateFlags; +typedef VkFlags VkCommandPoolTrimFlags; +typedef VkFlags VkDescriptorUpdateTemplateCreateFlags; + +typedef enum VkExternalMemoryHandleTypeFlagBits { + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT = 0x00000008, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT = 0x00000010, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 0x00000020, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 0x00000040, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT = 0x00000200, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT = 0x00000080, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT = 0x00000100, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalMemoryHandleTypeFlagBits; +typedef VkFlags VkExternalMemoryHandleTypeFlags; + +typedef enum VkExternalMemoryFeatureFlagBits { + VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT = 0x00000001, + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT = 0x00000002, + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 0x00000004, + VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT, + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT, + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT, + VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalMemoryFeatureFlagBits; +typedef VkFlags VkExternalMemoryFeatureFlags; + +typedef enum VkExternalFenceHandleTypeFlagBits { + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004, + VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000008, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, + VK_EXTERNAL_FENCE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalFenceHandleTypeFlagBits; +typedef VkFlags VkExternalFenceHandleTypeFlags; + +typedef enum VkExternalFenceFeatureFlagBits { + VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT = 0x00000001, + VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 0x00000002, + VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT, + VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT, + VK_EXTERNAL_FENCE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalFenceFeatureFlagBits; +typedef VkFlags VkExternalFenceFeatureFlags; + +typedef enum VkFenceImportFlagBits { + VK_FENCE_IMPORT_TEMPORARY_BIT = 0x00000001, + VK_FENCE_IMPORT_TEMPORARY_BIT_KHR = VK_FENCE_IMPORT_TEMPORARY_BIT, + VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFenceImportFlagBits; +typedef VkFlags VkFenceImportFlags; + +typedef enum VkSemaphoreImportFlagBits { + VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 0x00000001, + VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, + VK_SEMAPHORE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreImportFlagBits; +typedef VkFlags VkSemaphoreImportFlags; + +typedef enum VkExternalSemaphoreHandleTypeFlagBits { + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0x00000008, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000010, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalSemaphoreHandleTypeFlagBits; +typedef VkFlags VkExternalSemaphoreHandleTypeFlags; + +typedef enum VkExternalSemaphoreFeatureFlagBits { + VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT = 0x00000001, + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 0x00000002, + VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT, + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT, + VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalSemaphoreFeatureFlagBits; +typedef VkFlags VkExternalSemaphoreFeatureFlags; + +typedef struct VkPhysicalDeviceSubgroupProperties { + VkStructureType sType; + void* pNext; + uint32_t subgroupSize; + VkShaderStageFlags supportedStages; + VkSubgroupFeatureFlags supportedOperations; + VkBool32 quadOperationsInAllStages; +} VkPhysicalDeviceSubgroupProperties; + +typedef struct VkBindBufferMemoryInfo { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; +} VkBindBufferMemoryInfo; + +typedef struct VkBindImageMemoryInfo { + VkStructureType sType; + const void* pNext; + VkImage image; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; +} VkBindImageMemoryInfo; + +typedef struct VkPhysicalDevice16BitStorageFeatures { + VkStructureType sType; + void* pNext; + VkBool32 storageBuffer16BitAccess; + VkBool32 uniformAndStorageBuffer16BitAccess; + VkBool32 storagePushConstant16; + VkBool32 storageInputOutput16; +} VkPhysicalDevice16BitStorageFeatures; + +typedef struct VkMemoryDedicatedRequirements { + VkStructureType sType; + void* pNext; + VkBool32 prefersDedicatedAllocation; + VkBool32 requiresDedicatedAllocation; +} VkMemoryDedicatedRequirements; + +typedef struct VkMemoryDedicatedAllocateInfo { + VkStructureType sType; + const void* pNext; + VkImage image; + VkBuffer buffer; +} VkMemoryDedicatedAllocateInfo; + +typedef struct VkMemoryAllocateFlagsInfo { + VkStructureType sType; + const void* pNext; + VkMemoryAllocateFlags flags; + uint32_t deviceMask; +} VkMemoryAllocateFlagsInfo; + +typedef struct VkDeviceGroupRenderPassBeginInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceMask; + uint32_t deviceRenderAreaCount; + const VkRect2D* pDeviceRenderAreas; +} VkDeviceGroupRenderPassBeginInfo; + +typedef struct VkDeviceGroupCommandBufferBeginInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceMask; +} VkDeviceGroupCommandBufferBeginInfo; + +typedef struct VkDeviceGroupSubmitInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const uint32_t* pWaitSemaphoreDeviceIndices; + uint32_t commandBufferCount; + const uint32_t* pCommandBufferDeviceMasks; + uint32_t signalSemaphoreCount; + const uint32_t* pSignalSemaphoreDeviceIndices; +} VkDeviceGroupSubmitInfo; + +typedef struct VkDeviceGroupBindSparseInfo { + VkStructureType sType; + const void* pNext; + uint32_t resourceDeviceIndex; + uint32_t memoryDeviceIndex; +} VkDeviceGroupBindSparseInfo; + +typedef struct VkBindBufferMemoryDeviceGroupInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; +} VkBindBufferMemoryDeviceGroupInfo; + +typedef struct VkBindImageMemoryDeviceGroupInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; + uint32_t splitInstanceBindRegionCount; + const VkRect2D* pSplitInstanceBindRegions; +} VkBindImageMemoryDeviceGroupInfo; + +typedef struct VkPhysicalDeviceGroupProperties { + VkStructureType sType; + void* pNext; + uint32_t physicalDeviceCount; + VkPhysicalDevice physicalDevices[VK_MAX_DEVICE_GROUP_SIZE]; + VkBool32 subsetAllocation; +} VkPhysicalDeviceGroupProperties; + +typedef struct VkDeviceGroupDeviceCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t physicalDeviceCount; + const VkPhysicalDevice* pPhysicalDevices; +} VkDeviceGroupDeviceCreateInfo; + +typedef struct VkBufferMemoryRequirementsInfo2 { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; +} VkBufferMemoryRequirementsInfo2; + +typedef struct VkImageMemoryRequirementsInfo2 { + VkStructureType sType; + const void* pNext; + VkImage image; +} VkImageMemoryRequirementsInfo2; + +typedef struct VkImageSparseMemoryRequirementsInfo2 { + VkStructureType sType; + const void* pNext; + VkImage image; +} VkImageSparseMemoryRequirementsInfo2; + +typedef struct VkMemoryRequirements2 { + VkStructureType sType; + void* pNext; + VkMemoryRequirements memoryRequirements; +} VkMemoryRequirements2; + +typedef struct VkSparseImageMemoryRequirements2 { + VkStructureType sType; + void* pNext; + VkSparseImageMemoryRequirements memoryRequirements; +} VkSparseImageMemoryRequirements2; + +typedef struct VkPhysicalDeviceFeatures2 { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceFeatures features; +} VkPhysicalDeviceFeatures2; + +typedef struct VkPhysicalDeviceProperties2 { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceProperties properties; +} VkPhysicalDeviceProperties2; + +typedef struct VkFormatProperties2 { + VkStructureType sType; + void* pNext; + VkFormatProperties formatProperties; +} VkFormatProperties2; + +typedef struct VkImageFormatProperties2 { + VkStructureType sType; + void* pNext; + VkImageFormatProperties imageFormatProperties; +} VkImageFormatProperties2; + +typedef struct VkPhysicalDeviceImageFormatInfo2 { + VkStructureType sType; + const void* pNext; + VkFormat format; + VkImageType type; + VkImageTiling tiling; + VkImageUsageFlags usage; + VkImageCreateFlags flags; +} VkPhysicalDeviceImageFormatInfo2; + +typedef struct VkQueueFamilyProperties2 { + VkStructureType sType; + void* pNext; + VkQueueFamilyProperties queueFamilyProperties; +} VkQueueFamilyProperties2; + +typedef struct VkPhysicalDeviceMemoryProperties2 { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceMemoryProperties memoryProperties; +} VkPhysicalDeviceMemoryProperties2; + +typedef struct VkSparseImageFormatProperties2 { + VkStructureType sType; + void* pNext; + VkSparseImageFormatProperties properties; +} VkSparseImageFormatProperties2; + +typedef struct VkPhysicalDeviceSparseImageFormatInfo2 { + VkStructureType sType; + const void* pNext; + VkFormat format; + VkImageType type; + VkSampleCountFlagBits samples; + VkImageUsageFlags usage; + VkImageTiling tiling; +} VkPhysicalDeviceSparseImageFormatInfo2; + +typedef struct VkPhysicalDevicePointClippingProperties { + VkStructureType sType; + void* pNext; + VkPointClippingBehavior pointClippingBehavior; +} VkPhysicalDevicePointClippingProperties; + +typedef struct VkInputAttachmentAspectReference { + uint32_t subpass; + uint32_t inputAttachmentIndex; + VkImageAspectFlags aspectMask; +} VkInputAttachmentAspectReference; + +typedef struct VkRenderPassInputAttachmentAspectCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t aspectReferenceCount; + const VkInputAttachmentAspectReference* pAspectReferences; +} VkRenderPassInputAttachmentAspectCreateInfo; + +typedef struct VkImageViewUsageCreateInfo { + VkStructureType sType; + const void* pNext; + VkImageUsageFlags usage; +} VkImageViewUsageCreateInfo; + +typedef struct VkPipelineTessellationDomainOriginStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkTessellationDomainOrigin domainOrigin; +} VkPipelineTessellationDomainOriginStateCreateInfo; + +typedef struct VkRenderPassMultiviewCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t subpassCount; + const uint32_t* pViewMasks; + uint32_t dependencyCount; + const int32_t* pViewOffsets; + uint32_t correlationMaskCount; + const uint32_t* pCorrelationMasks; +} VkRenderPassMultiviewCreateInfo; + +typedef struct VkPhysicalDeviceMultiviewFeatures { + VkStructureType sType; + void* pNext; + VkBool32 multiview; + VkBool32 multiviewGeometryShader; + VkBool32 multiviewTessellationShader; +} VkPhysicalDeviceMultiviewFeatures; + +typedef struct VkPhysicalDeviceMultiviewProperties { + VkStructureType sType; + void* pNext; + uint32_t maxMultiviewViewCount; + uint32_t maxMultiviewInstanceIndex; +} VkPhysicalDeviceMultiviewProperties; + +typedef struct VkPhysicalDeviceVariablePointerFeatures { + VkStructureType sType; + void* pNext; + VkBool32 variablePointersStorageBuffer; + VkBool32 variablePointers; +} VkPhysicalDeviceVariablePointerFeatures; + +typedef struct VkPhysicalDeviceProtectedMemoryFeatures { + VkStructureType sType; + void* pNext; + VkBool32 protectedMemory; +} VkPhysicalDeviceProtectedMemoryFeatures; + +typedef struct VkPhysicalDeviceProtectedMemoryProperties { + VkStructureType sType; + void* pNext; + VkBool32 protectedNoFault; +} VkPhysicalDeviceProtectedMemoryProperties; + +typedef struct VkDeviceQueueInfo2 { + VkStructureType sType; + const void* pNext; + VkDeviceQueueCreateFlags flags; + uint32_t queueFamilyIndex; + uint32_t queueIndex; +} VkDeviceQueueInfo2; + +typedef struct VkProtectedSubmitInfo { + VkStructureType sType; + const void* pNext; + VkBool32 protectedSubmit; +} VkProtectedSubmitInfo; + +typedef struct VkSamplerYcbcrConversionCreateInfo { + VkStructureType sType; + const void* pNext; + VkFormat format; + VkSamplerYcbcrModelConversion ycbcrModel; + VkSamplerYcbcrRange ycbcrRange; + VkComponentMapping components; + VkChromaLocation xChromaOffset; + VkChromaLocation yChromaOffset; + VkFilter chromaFilter; + VkBool32 forceExplicitReconstruction; +} VkSamplerYcbcrConversionCreateInfo; + +typedef struct VkSamplerYcbcrConversionInfo { + VkStructureType sType; + const void* pNext; + VkSamplerYcbcrConversion conversion; +} VkSamplerYcbcrConversionInfo; + +typedef struct VkBindImagePlaneMemoryInfo { + VkStructureType sType; + const void* pNext; + VkImageAspectFlagBits planeAspect; +} VkBindImagePlaneMemoryInfo; + +typedef struct VkImagePlaneMemoryRequirementsInfo { + VkStructureType sType; + const void* pNext; + VkImageAspectFlagBits planeAspect; +} VkImagePlaneMemoryRequirementsInfo; + +typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeatures { + VkStructureType sType; + void* pNext; + VkBool32 samplerYcbcrConversion; +} VkPhysicalDeviceSamplerYcbcrConversionFeatures; + +typedef struct VkSamplerYcbcrConversionImageFormatProperties { + VkStructureType sType; + void* pNext; + uint32_t combinedImageSamplerDescriptorCount; +} VkSamplerYcbcrConversionImageFormatProperties; + +typedef struct VkDescriptorUpdateTemplateEntry { + uint32_t dstBinding; + uint32_t dstArrayElement; + uint32_t descriptorCount; + VkDescriptorType descriptorType; + size_t offset; + size_t stride; +} VkDescriptorUpdateTemplateEntry; + +typedef struct VkDescriptorUpdateTemplateCreateInfo { + VkStructureType sType; + void* pNext; + VkDescriptorUpdateTemplateCreateFlags flags; + uint32_t descriptorUpdateEntryCount; + const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries; + VkDescriptorUpdateTemplateType templateType; + VkDescriptorSetLayout descriptorSetLayout; + VkPipelineBindPoint pipelineBindPoint; + VkPipelineLayout pipelineLayout; + uint32_t set; +} VkDescriptorUpdateTemplateCreateInfo; + +typedef struct VkExternalMemoryProperties { + VkExternalMemoryFeatureFlags externalMemoryFeatures; + VkExternalMemoryHandleTypeFlags exportFromImportedHandleTypes; + VkExternalMemoryHandleTypeFlags compatibleHandleTypes; +} VkExternalMemoryProperties; + +typedef struct VkPhysicalDeviceExternalImageFormatInfo { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalImageFormatInfo; + +typedef struct VkExternalImageFormatProperties { + VkStructureType sType; + void* pNext; + VkExternalMemoryProperties externalMemoryProperties; +} VkExternalImageFormatProperties; + +typedef struct VkPhysicalDeviceExternalBufferInfo { + VkStructureType sType; + const void* pNext; + VkBufferCreateFlags flags; + VkBufferUsageFlags usage; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalBufferInfo; + +typedef struct VkExternalBufferProperties { + VkStructureType sType; + void* pNext; + VkExternalMemoryProperties externalMemoryProperties; +} VkExternalBufferProperties; + +typedef struct VkPhysicalDeviceIDProperties { + VkStructureType sType; + void* pNext; + uint8_t deviceUUID[VK_UUID_SIZE]; + uint8_t driverUUID[VK_UUID_SIZE]; + uint8_t deviceLUID[VK_LUID_SIZE]; + uint32_t deviceNodeMask; + VkBool32 deviceLUIDValid; +} VkPhysicalDeviceIDProperties; + +typedef struct VkExternalMemoryImageCreateInfo { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlags handleTypes; +} VkExternalMemoryImageCreateInfo; + +typedef struct VkExternalMemoryBufferCreateInfo { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlags handleTypes; +} VkExternalMemoryBufferCreateInfo; + +typedef struct VkExportMemoryAllocateInfo { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlags handleTypes; +} VkExportMemoryAllocateInfo; + +typedef struct VkPhysicalDeviceExternalFenceInfo { + VkStructureType sType; + const void* pNext; + VkExternalFenceHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalFenceInfo; + +typedef struct VkExternalFenceProperties { + VkStructureType sType; + void* pNext; + VkExternalFenceHandleTypeFlags exportFromImportedHandleTypes; + VkExternalFenceHandleTypeFlags compatibleHandleTypes; + VkExternalFenceFeatureFlags externalFenceFeatures; +} VkExternalFenceProperties; + +typedef struct VkExportFenceCreateInfo { + VkStructureType sType; + const void* pNext; + VkExternalFenceHandleTypeFlags handleTypes; +} VkExportFenceCreateInfo; + +typedef struct VkExportSemaphoreCreateInfo { + VkStructureType sType; + const void* pNext; + VkExternalSemaphoreHandleTypeFlags handleTypes; +} VkExportSemaphoreCreateInfo; + +typedef struct VkPhysicalDeviceExternalSemaphoreInfo { + VkStructureType sType; + const void* pNext; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalSemaphoreInfo; + +typedef struct VkExternalSemaphoreProperties { + VkStructureType sType; + void* pNext; + VkExternalSemaphoreHandleTypeFlags exportFromImportedHandleTypes; + VkExternalSemaphoreHandleTypeFlags compatibleHandleTypes; + VkExternalSemaphoreFeatureFlags externalSemaphoreFeatures; +} VkExternalSemaphoreProperties; + +typedef struct VkPhysicalDeviceMaintenance3Properties { + VkStructureType sType; + void* pNext; + uint32_t maxPerSetDescriptors; + VkDeviceSize maxMemoryAllocationSize; +} VkPhysicalDeviceMaintenance3Properties; + +typedef struct VkDescriptorSetLayoutSupport { + VkStructureType sType; + void* pNext; + VkBool32 supported; +} VkDescriptorSetLayoutSupport; + +typedef struct VkPhysicalDeviceShaderDrawParameterFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderDrawParameters; +} VkPhysicalDeviceShaderDrawParameterFeatures; + + +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceVersion)(uint32_t* pApiVersion); +typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos); +typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeatures)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); +typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMask)(VkCommandBuffer commandBuffer, uint32_t deviceMask); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchBase)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroups)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); +typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties); +typedef void (VKAPI_PTR *PFN_vkTrimCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); +typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue2)(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue); +typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversion)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion); +typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversion)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplate)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplate)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplate)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFenceProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphoreProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupport)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceVersion( + uint32_t* pApiVersion); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2( + VkDevice device, + uint32_t bindInfoCount, + const VkBindBufferMemoryInfo* pBindInfos); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2( + VkDevice device, + uint32_t bindInfoCount, + const VkBindImageMemoryInfo* pBindInfos); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeatures( + VkDevice device, + uint32_t heapIndex, + uint32_t localDeviceIndex, + uint32_t remoteDeviceIndex, + VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMask( + VkCommandBuffer commandBuffer, + uint32_t deviceMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBase( + VkCommandBuffer commandBuffer, + uint32_t baseGroupX, + uint32_t baseGroupY, + uint32_t baseGroupZ, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups( + VkInstance instance, + uint32_t* pPhysicalDeviceGroupCount, + VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2( + VkDevice device, + const VkImageMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2( + VkDevice device, + const VkBufferMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2( + VkDevice device, + const VkImageSparseMemoryRequirementsInfo2* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures2* pFeatures); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceProperties2* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkFormatProperties2* pFormatProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, + VkImageFormatProperties2* pImageFormatProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2( + VkPhysicalDevice physicalDevice, + uint32_t* pQueueFamilyPropertyCount, + VkQueueFamilyProperties2* pQueueFamilyProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties2* pMemoryProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, + uint32_t* pPropertyCount, + VkSparseImageFormatProperties2* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkTrimCommandPool( + VkDevice device, + VkCommandPool commandPool, + VkCommandPoolTrimFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue2( + VkDevice device, + const VkDeviceQueueInfo2* pQueueInfo, + VkQueue* pQueue); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversion( + VkDevice device, + const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSamplerYcbcrConversion* pYcbcrConversion); + +VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversion( + VkDevice device, + VkSamplerYcbcrConversion ycbcrConversion, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplate( + VkDevice device, + const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplate( + VkDevice device, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplate( + VkDevice device, + VkDescriptorSet descriptorSet, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const void* pData); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, + VkExternalBufferProperties* pExternalBufferProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFenceProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, + VkExternalFenceProperties* pExternalFenceProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphoreProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, + VkExternalSemaphoreProperties* pExternalSemaphoreProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport( + VkDevice device, + const VkDescriptorSetLayoutCreateInfo* pCreateInfo, + VkDescriptorSetLayoutSupport* pSupport); +#endif + +#define VK_KHR_surface 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) + +#define VK_KHR_SURFACE_SPEC_VERSION 25 +#define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface" +#define VK_COLORSPACE_SRGB_NONLINEAR_KHR VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + + +typedef enum VkColorSpaceKHR { + VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0, + VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001, + VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002, + VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104003, + VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004, + VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005, + VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006, + VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007, + VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008, + VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009, + VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010, + VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011, + VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012, + VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013, + VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014, + VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, + VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, + VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1), + VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkColorSpaceKHR; + +typedef enum VkPresentModeKHR { + VK_PRESENT_MODE_IMMEDIATE_KHR = 0, + VK_PRESENT_MODE_MAILBOX_KHR = 1, + VK_PRESENT_MODE_FIFO_KHR = 2, + VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, + VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000, + VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001, + VK_PRESENT_MODE_BEGIN_RANGE_KHR = VK_PRESENT_MODE_IMMEDIATE_KHR, + VK_PRESENT_MODE_END_RANGE_KHR = VK_PRESENT_MODE_FIFO_RELAXED_KHR, + VK_PRESENT_MODE_RANGE_SIZE_KHR = (VK_PRESENT_MODE_FIFO_RELAXED_KHR - VK_PRESENT_MODE_IMMEDIATE_KHR + 1), + VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPresentModeKHR; + + +typedef enum VkSurfaceTransformFlagBitsKHR { + VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001, + VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002, + VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0x00000004, + VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0x00000008, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0x00000010, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0x00000020, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080, + VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100, + VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkSurfaceTransformFlagBitsKHR; +typedef VkFlags VkSurfaceTransformFlagsKHR; + +typedef enum VkCompositeAlphaFlagBitsKHR { + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008, + VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkCompositeAlphaFlagBitsKHR; +typedef VkFlags VkCompositeAlphaFlagsKHR; + +typedef struct VkSurfaceCapabilitiesKHR { + uint32_t minImageCount; + uint32_t maxImageCount; + VkExtent2D currentExtent; + VkExtent2D minImageExtent; + VkExtent2D maxImageExtent; + uint32_t maxImageArrayLayers; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkSurfaceTransformFlagBitsKHR currentTransform; + VkCompositeAlphaFlagsKHR supportedCompositeAlpha; + VkImageUsageFlags supportedUsageFlags; +} VkSurfaceCapabilitiesKHR; + +typedef struct VkSurfaceFormatKHR { + VkFormat format; + VkColorSpaceKHR colorSpace; +} VkSurfaceFormatKHR; + + +typedef void (VKAPI_PTR *PFN_vkDestroySurfaceKHR)(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR( + VkInstance instance, + VkSurfaceKHR surface, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + VkSurfaceKHR surface, + VkBool32* pSupported); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + uint32_t* pSurfaceFormatCount, + VkSurfaceFormatKHR* pSurfaceFormats); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + uint32_t* pPresentModeCount, + VkPresentModeKHR* pPresentModes); +#endif + +#define VK_KHR_swapchain 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR) + +#define VK_KHR_SWAPCHAIN_SPEC_VERSION 70 +#define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain" + + +typedef enum VkSwapchainCreateFlagBitsKHR { + VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001, + VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002, + VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkSwapchainCreateFlagBitsKHR; +typedef VkFlags VkSwapchainCreateFlagsKHR; + +typedef enum VkDeviceGroupPresentModeFlagBitsKHR { + VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 0x00000001, + VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 0x00000002, + VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 0x00000004, + VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0x00000008, + VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDeviceGroupPresentModeFlagBitsKHR; +typedef VkFlags VkDeviceGroupPresentModeFlagsKHR; + +typedef struct VkSwapchainCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainCreateFlagsKHR flags; + VkSurfaceKHR surface; + uint32_t minImageCount; + VkFormat imageFormat; + VkColorSpaceKHR imageColorSpace; + VkExtent2D imageExtent; + uint32_t imageArrayLayers; + VkImageUsageFlags imageUsage; + VkSharingMode imageSharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; + VkSurfaceTransformFlagBitsKHR preTransform; + VkCompositeAlphaFlagBitsKHR compositeAlpha; + VkPresentModeKHR presentMode; + VkBool32 clipped; + VkSwapchainKHR oldSwapchain; +} VkSwapchainCreateInfoKHR; + +typedef struct VkPresentInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const VkSemaphore* pWaitSemaphores; + uint32_t swapchainCount; + const VkSwapchainKHR* pSwapchains; + const uint32_t* pImageIndices; + VkResult* pResults; +} VkPresentInfoKHR; + +typedef struct VkImageSwapchainCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; +} VkImageSwapchainCreateInfoKHR; + +typedef struct VkBindImageMemorySwapchainInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + uint32_t imageIndex; +} VkBindImageMemorySwapchainInfoKHR; + +typedef struct VkAcquireNextImageInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + uint64_t timeout; + VkSemaphore semaphore; + VkFence fence; + uint32_t deviceMask; +} VkAcquireNextImageInfoKHR; + +typedef struct VkDeviceGroupPresentCapabilitiesKHR { + VkStructureType sType; + const void* pNext; + uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE]; + VkDeviceGroupPresentModeFlagsKHR modes; +} VkDeviceGroupPresentCapabilitiesKHR; + +typedef struct VkDeviceGroupPresentInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const uint32_t* pDeviceMasks; + VkDeviceGroupPresentModeFlagBitsKHR mode; +} VkDeviceGroupPresentInfoKHR; + +typedef struct VkDeviceGroupSwapchainCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceGroupPresentModeFlagsKHR modes; +} VkDeviceGroupSwapchainCreateInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateSwapchainKHR)(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain); +typedef void (VKAPI_PTR *PFN_vkDestroySwapchainKHR)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImageKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex); +typedef VkResult (VKAPI_PTR *PFN_vkQueuePresentKHR)(VkQueue queue, const VkPresentInfoKHR* pPresentInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHR)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHR)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHR)(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR( + VkDevice device, + const VkSwapchainCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSwapchainKHR* pSwapchain); + +VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR( + VkDevice device, + VkSwapchainKHR swapchain, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t* pSwapchainImageCount, + VkImage* pSwapchainImages); + +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t timeout, + VkSemaphore semaphore, + VkFence fence, + uint32_t* pImageIndex); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR( + VkQueue queue, + const VkPresentInfoKHR* pPresentInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHR( + VkDevice device, + VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHR( + VkDevice device, + VkSurfaceKHR surface, + VkDeviceGroupPresentModeFlagsKHR* pModes); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + uint32_t* pRectCount, + VkRect2D* pRects); + +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR( + VkDevice device, + const VkAcquireNextImageInfoKHR* pAcquireInfo, + uint32_t* pImageIndex); +#endif + +#define VK_KHR_display 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayModeKHR) + +#define VK_KHR_DISPLAY_SPEC_VERSION 21 +#define VK_KHR_DISPLAY_EXTENSION_NAME "VK_KHR_display" + + +typedef enum VkDisplayPlaneAlphaFlagBitsKHR { + VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, + VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002, + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0x00000004, + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008, + VK_DISPLAY_PLANE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDisplayPlaneAlphaFlagBitsKHR; +typedef VkFlags VkDisplayPlaneAlphaFlagsKHR; +typedef VkFlags VkDisplayModeCreateFlagsKHR; +typedef VkFlags VkDisplaySurfaceCreateFlagsKHR; + +typedef struct VkDisplayPropertiesKHR { + VkDisplayKHR display; + const char* displayName; + VkExtent2D physicalDimensions; + VkExtent2D physicalResolution; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkBool32 planeReorderPossible; + VkBool32 persistentContent; +} VkDisplayPropertiesKHR; + +typedef struct VkDisplayModeParametersKHR { + VkExtent2D visibleRegion; + uint32_t refreshRate; +} VkDisplayModeParametersKHR; + +typedef struct VkDisplayModePropertiesKHR { + VkDisplayModeKHR displayMode; + VkDisplayModeParametersKHR parameters; +} VkDisplayModePropertiesKHR; + +typedef struct VkDisplayModeCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDisplayModeCreateFlagsKHR flags; + VkDisplayModeParametersKHR parameters; +} VkDisplayModeCreateInfoKHR; + +typedef struct VkDisplayPlaneCapabilitiesKHR { + VkDisplayPlaneAlphaFlagsKHR supportedAlpha; + VkOffset2D minSrcPosition; + VkOffset2D maxSrcPosition; + VkExtent2D minSrcExtent; + VkExtent2D maxSrcExtent; + VkOffset2D minDstPosition; + VkOffset2D maxDstPosition; + VkExtent2D minDstExtent; + VkExtent2D maxDstExtent; +} VkDisplayPlaneCapabilitiesKHR; + +typedef struct VkDisplayPlanePropertiesKHR { + VkDisplayKHR currentDisplay; + uint32_t currentStackIndex; +} VkDisplayPlanePropertiesKHR; + +typedef struct VkDisplaySurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDisplaySurfaceCreateFlagsKHR flags; + VkDisplayModeKHR displayMode; + uint32_t planeIndex; + uint32_t planeStackIndex; + VkSurfaceTransformFlagBitsKHR transform; + float globalAlpha; + VkDisplayPlaneAlphaFlagBitsKHR alphaMode; + VkExtent2D imageExtent; +} VkDisplaySurfaceCreateInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneSupportedDisplaysKHR)(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModePropertiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayModeKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayPlaneSurfaceKHR)(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayPropertiesKHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlanePropertiesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayPlanePropertiesKHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneSupportedDisplaysKHR( + VkPhysicalDevice physicalDevice, + uint32_t planeIndex, + uint32_t* pDisplayCount, + VkDisplayKHR* pDisplays); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display, + uint32_t* pPropertyCount, + VkDisplayModePropertiesKHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display, + const VkDisplayModeCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDisplayModeKHR* pMode); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + VkDisplayModeKHR mode, + uint32_t planeIndex, + VkDisplayPlaneCapabilitiesKHR* pCapabilities); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR( + VkInstance instance, + const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#define VK_KHR_display_swapchain 1 +#define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION 9 +#define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME "VK_KHR_display_swapchain" + +typedef struct VkDisplayPresentInfoKHR { + VkStructureType sType; + const void* pNext; + VkRect2D srcRect; + VkRect2D dstRect; + VkBool32 persistent; +} VkDisplayPresentInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateSharedSwapchainsKHR)(VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( + VkDevice device, + uint32_t swapchainCount, + const VkSwapchainCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkSwapchainKHR* pSwapchains); +#endif + +#define VK_KHR_sampler_mirror_clamp_to_edge 1 +#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 1 +#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge" + + +#define VK_KHR_multiview 1 +#define VK_KHR_MULTIVIEW_SPEC_VERSION 1 +#define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview" + +typedef VkRenderPassMultiviewCreateInfo VkRenderPassMultiviewCreateInfoKHR; + +typedef VkPhysicalDeviceMultiviewFeatures VkPhysicalDeviceMultiviewFeaturesKHR; + +typedef VkPhysicalDeviceMultiviewProperties VkPhysicalDeviceMultiviewPropertiesKHR; + + + +#define VK_KHR_get_physical_device_properties2 1 +#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 1 +#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2" + +typedef VkPhysicalDeviceFeatures2 VkPhysicalDeviceFeatures2KHR; + +typedef VkPhysicalDeviceProperties2 VkPhysicalDeviceProperties2KHR; + +typedef VkFormatProperties2 VkFormatProperties2KHR; + +typedef VkImageFormatProperties2 VkImageFormatProperties2KHR; + +typedef VkPhysicalDeviceImageFormatInfo2 VkPhysicalDeviceImageFormatInfo2KHR; + +typedef VkQueueFamilyProperties2 VkQueueFamilyProperties2KHR; + +typedef VkPhysicalDeviceMemoryProperties2 VkPhysicalDeviceMemoryProperties2KHR; + +typedef VkSparseImageFormatProperties2 VkSparseImageFormatProperties2KHR; + +typedef VkPhysicalDeviceSparseImageFormatInfo2 VkPhysicalDeviceSparseImageFormatInfo2KHR; + + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures2* pFeatures); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceProperties2* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkFormatProperties2* pFormatProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, + VkImageFormatProperties2* pImageFormatProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR( + VkPhysicalDevice physicalDevice, + uint32_t* pQueueFamilyPropertyCount, + VkQueueFamilyProperties2* pQueueFamilyProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties2* pMemoryProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, + uint32_t* pPropertyCount, + VkSparseImageFormatProperties2* pProperties); +#endif + +#define VK_KHR_device_group 1 +#define VK_KHR_DEVICE_GROUP_SPEC_VERSION 3 +#define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group" + +typedef VkPeerMemoryFeatureFlags VkPeerMemoryFeatureFlagsKHR; + +typedef VkPeerMemoryFeatureFlagBits VkPeerMemoryFeatureFlagBitsKHR; + +typedef VkMemoryAllocateFlags VkMemoryAllocateFlagsKHR; + +typedef VkMemoryAllocateFlagBits VkMemoryAllocateFlagBitsKHR; + + +typedef VkMemoryAllocateFlagsInfo VkMemoryAllocateFlagsInfoKHR; + +typedef VkDeviceGroupRenderPassBeginInfo VkDeviceGroupRenderPassBeginInfoKHR; + +typedef VkDeviceGroupCommandBufferBeginInfo VkDeviceGroupCommandBufferBeginInfoKHR; + +typedef VkDeviceGroupSubmitInfo VkDeviceGroupSubmitInfoKHR; + +typedef VkDeviceGroupBindSparseInfo VkDeviceGroupBindSparseInfoKHR; + +typedef VkBindBufferMemoryDeviceGroupInfo VkBindBufferMemoryDeviceGroupInfoKHR; + +typedef VkBindImageMemoryDeviceGroupInfo VkBindImageMemoryDeviceGroupInfoKHR; + + +typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); +typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHR)(VkCommandBuffer commandBuffer, uint32_t deviceMask); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHR)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHR( + VkDevice device, + uint32_t heapIndex, + uint32_t localDeviceIndex, + uint32_t remoteDeviceIndex, + VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHR( + VkCommandBuffer commandBuffer, + uint32_t deviceMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR( + VkCommandBuffer commandBuffer, + uint32_t baseGroupX, + uint32_t baseGroupY, + uint32_t baseGroupZ, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); +#endif + +#define VK_KHR_shader_draw_parameters 1 +#define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1 +#define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters" + + +#define VK_KHR_maintenance1 1 +#define VK_KHR_MAINTENANCE1_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1" + +typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR; + + +typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR( + VkDevice device, + VkCommandPool commandPool, + VkCommandPoolTrimFlags flags); +#endif + +#define VK_KHR_device_group_creation 1 +#define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1 +#define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation" +#define VK_MAX_DEVICE_GROUP_SIZE_KHR VK_MAX_DEVICE_GROUP_SIZE + +typedef VkPhysicalDeviceGroupProperties VkPhysicalDeviceGroupPropertiesKHR; + +typedef VkDeviceGroupDeviceCreateInfo VkDeviceGroupDeviceCreateInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHR)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHR( + VkInstance instance, + uint32_t* pPhysicalDeviceGroupCount, + VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); +#endif + +#define VK_KHR_external_memory_capabilities 1 +#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities" +#define VK_LUID_SIZE_KHR VK_LUID_SIZE + +typedef VkExternalMemoryHandleTypeFlags VkExternalMemoryHandleTypeFlagsKHR; + +typedef VkExternalMemoryHandleTypeFlagBits VkExternalMemoryHandleTypeFlagBitsKHR; + +typedef VkExternalMemoryFeatureFlags VkExternalMemoryFeatureFlagsKHR; + +typedef VkExternalMemoryFeatureFlagBits VkExternalMemoryFeatureFlagBitsKHR; + + +typedef VkExternalMemoryProperties VkExternalMemoryPropertiesKHR; + +typedef VkPhysicalDeviceExternalImageFormatInfo VkPhysicalDeviceExternalImageFormatInfoKHR; + +typedef VkExternalImageFormatProperties VkExternalImageFormatPropertiesKHR; + +typedef VkPhysicalDeviceExternalBufferInfo VkPhysicalDeviceExternalBufferInfoKHR; + +typedef VkExternalBufferProperties VkExternalBufferPropertiesKHR; + +typedef VkPhysicalDeviceIDProperties VkPhysicalDeviceIDPropertiesKHR; + + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, + VkExternalBufferProperties* pExternalBufferProperties); +#endif + +#define VK_KHR_external_memory 1 +#define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory" +#define VK_QUEUE_FAMILY_EXTERNAL_KHR VK_QUEUE_FAMILY_EXTERNAL + +typedef VkExternalMemoryImageCreateInfo VkExternalMemoryImageCreateInfoKHR; + +typedef VkExternalMemoryBufferCreateInfo VkExternalMemoryBufferCreateInfoKHR; + +typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR; + + + +#define VK_KHR_external_memory_fd 1 +#define VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd" + +typedef struct VkImportMemoryFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + int fd; +} VkImportMemoryFdInfoKHR; + +typedef struct VkMemoryFdPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryFdPropertiesKHR; + +typedef struct VkMemoryGetFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetFdInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHR)(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHR( + VkDevice device, + const VkMemoryGetFdInfoKHR* pGetFdInfo, + int* pFd); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + int fd, + VkMemoryFdPropertiesKHR* pMemoryFdProperties); +#endif + +#define VK_KHR_external_semaphore_capabilities 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities" + +typedef VkExternalSemaphoreHandleTypeFlags VkExternalSemaphoreHandleTypeFlagsKHR; + +typedef VkExternalSemaphoreHandleTypeFlagBits VkExternalSemaphoreHandleTypeFlagBitsKHR; + +typedef VkExternalSemaphoreFeatureFlags VkExternalSemaphoreFeatureFlagsKHR; + +typedef VkExternalSemaphoreFeatureFlagBits VkExternalSemaphoreFeatureFlagBitsKHR; + + +typedef VkPhysicalDeviceExternalSemaphoreInfo VkPhysicalDeviceExternalSemaphoreInfoKHR; + +typedef VkExternalSemaphoreProperties VkExternalSemaphorePropertiesKHR; + + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, + VkExternalSemaphoreProperties* pExternalSemaphoreProperties); +#endif + +#define VK_KHR_external_semaphore 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore" + +typedef VkSemaphoreImportFlags VkSemaphoreImportFlagsKHR; + +typedef VkSemaphoreImportFlagBits VkSemaphoreImportFlagBitsKHR; + + +typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR; + + + +#define VK_KHR_external_semaphore_fd 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd" + +typedef struct VkImportSemaphoreFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkSemaphoreImportFlags flags; + VkExternalSemaphoreHandleTypeFlagBits handleType; + int fd; +} VkImportSemaphoreFdInfoKHR; + +typedef struct VkSemaphoreGetFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkSemaphoreGetFdInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFdKHR)(VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFdKHR)(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFdKHR( + VkDevice device, + const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHR( + VkDevice device, + const VkSemaphoreGetFdInfoKHR* pGetFdInfo, + int* pFd); +#endif + +#define VK_KHR_push_descriptor 1 +#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2 +#define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor" + +typedef struct VkPhysicalDevicePushDescriptorPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t maxPushDescriptors; +} VkPhysicalDevicePushDescriptorPropertiesKHR; + + +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetKHR)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR( + VkCommandBuffer commandBuffer, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + VkPipelineLayout layout, + uint32_t set, + const void* pData); +#endif + +#define VK_KHR_16bit_storage 1 +#define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1 +#define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage" + +typedef VkPhysicalDevice16BitStorageFeatures VkPhysicalDevice16BitStorageFeaturesKHR; + + + +#define VK_KHR_incremental_present 1 +#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1 +#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present" + +typedef struct VkRectLayerKHR { + VkOffset2D offset; + VkExtent2D extent; + uint32_t layer; +} VkRectLayerKHR; + +typedef struct VkPresentRegionKHR { + uint32_t rectangleCount; + const VkRectLayerKHR* pRectangles; +} VkPresentRegionKHR; + +typedef struct VkPresentRegionsKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentRegionKHR* pRegions; +} VkPresentRegionsKHR; + + + +#define VK_KHR_descriptor_update_template 1 +typedef VkDescriptorUpdateTemplate VkDescriptorUpdateTemplateKHR; + + +#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1 +#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template" + +typedef VkDescriptorUpdateTemplateType VkDescriptorUpdateTemplateTypeKHR; + + +typedef VkDescriptorUpdateTemplateCreateFlags VkDescriptorUpdateTemplateCreateFlagsKHR; + + +typedef VkDescriptorUpdateTemplateEntry VkDescriptorUpdateTemplateEntryKHR; + +typedef VkDescriptorUpdateTemplateCreateInfo VkDescriptorUpdateTemplateCreateInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplateKHR( + VkDevice device, + const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplateKHR( + VkDevice device, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR( + VkDevice device, + VkDescriptorSet descriptorSet, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const void* pData); +#endif + +#define VK_KHR_shared_presentable_image 1 +#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1 +#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image" + +typedef struct VkSharedPresentSurfaceCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkImageUsageFlags sharedPresentSupportedUsageFlags; +} VkSharedPresentSurfaceCapabilitiesKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR( + VkDevice device, + VkSwapchainKHR swapchain); +#endif + +#define VK_KHR_external_fence_capabilities 1 +#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities" + +typedef VkExternalFenceHandleTypeFlags VkExternalFenceHandleTypeFlagsKHR; + +typedef VkExternalFenceHandleTypeFlagBits VkExternalFenceHandleTypeFlagBitsKHR; + +typedef VkExternalFenceFeatureFlags VkExternalFenceFeatureFlagsKHR; + +typedef VkExternalFenceFeatureFlagBits VkExternalFenceFeatureFlagBitsKHR; + + +typedef VkPhysicalDeviceExternalFenceInfo VkPhysicalDeviceExternalFenceInfoKHR; + +typedef VkExternalFenceProperties VkExternalFencePropertiesKHR; + + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, + VkExternalFenceProperties* pExternalFenceProperties); +#endif + +#define VK_KHR_external_fence 1 +#define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence" + +typedef VkFenceImportFlags VkFenceImportFlagsKHR; + +typedef VkFenceImportFlagBits VkFenceImportFlagBitsKHR; + + +typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR; + + + +#define VK_KHR_external_fence_fd 1 +#define VK_KHR_EXTERNAL_FENCE_FD_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd" + +typedef struct VkImportFenceFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkFenceImportFlags flags; + VkExternalFenceHandleTypeFlagBits handleType; + int fd; +} VkImportFenceFdInfoKHR; + +typedef struct VkFenceGetFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkExternalFenceHandleTypeFlagBits handleType; +} VkFenceGetFdInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkImportFenceFdKHR)(VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetFenceFdKHR)(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceFdKHR( + VkDevice device, + const VkImportFenceFdInfoKHR* pImportFenceFdInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceFdKHR( + VkDevice device, + const VkFenceGetFdInfoKHR* pGetFdInfo, + int* pFd); +#endif + +#define VK_KHR_maintenance2 1 +#define VK_KHR_MAINTENANCE2_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2" + +typedef VkPointClippingBehavior VkPointClippingBehaviorKHR; + +typedef VkTessellationDomainOrigin VkTessellationDomainOriginKHR; + + +typedef VkPhysicalDevicePointClippingProperties VkPhysicalDevicePointClippingPropertiesKHR; + +typedef VkRenderPassInputAttachmentAspectCreateInfo VkRenderPassInputAttachmentAspectCreateInfoKHR; + +typedef VkInputAttachmentAspectReference VkInputAttachmentAspectReferenceKHR; + +typedef VkImageViewUsageCreateInfo VkImageViewUsageCreateInfoKHR; + +typedef VkPipelineTessellationDomainOriginStateCreateInfo VkPipelineTessellationDomainOriginStateCreateInfoKHR; + + + +#define VK_KHR_get_surface_capabilities2 1 +#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1 +#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2" + +typedef struct VkPhysicalDeviceSurfaceInfo2KHR { + VkStructureType sType; + const void* pNext; + VkSurfaceKHR surface; +} VkPhysicalDeviceSurfaceInfo2KHR; + +typedef struct VkSurfaceCapabilities2KHR { + VkStructureType sType; + void* pNext; + VkSurfaceCapabilitiesKHR surfaceCapabilities; +} VkSurfaceCapabilities2KHR; + +typedef struct VkSurfaceFormat2KHR { + VkStructureType sType; + void* pNext; + VkSurfaceFormatKHR surfaceFormat; +} VkSurfaceFormat2KHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + VkSurfaceCapabilities2KHR* pSurfaceCapabilities); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + uint32_t* pSurfaceFormatCount, + VkSurfaceFormat2KHR* pSurfaceFormats); +#endif + +#define VK_KHR_variable_pointers 1 +#define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1 +#define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers" + +typedef VkPhysicalDeviceVariablePointerFeatures VkPhysicalDeviceVariablePointerFeaturesKHR; + + + +#define VK_KHR_dedicated_allocation 1 +#define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3 +#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation" + +typedef VkMemoryDedicatedRequirements VkMemoryDedicatedRequirementsKHR; + +typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR; + + + +#define VK_KHR_storage_buffer_storage_class 1 +#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION 1 +#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME "VK_KHR_storage_buffer_storage_class" + + +#define VK_KHR_relaxed_block_layout 1 +#define VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME "VK_KHR_relaxed_block_layout" + + +#define VK_KHR_get_memory_requirements2 1 +#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1 +#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME "VK_KHR_get_memory_requirements2" + +typedef VkBufferMemoryRequirementsInfo2 VkBufferMemoryRequirementsInfo2KHR; + +typedef VkImageMemoryRequirementsInfo2 VkImageMemoryRequirementsInfo2KHR; + +typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR; + +typedef VkMemoryRequirements2 VkMemoryRequirements2KHR; + +typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR; + + +typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR( + VkDevice device, + const VkImageMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2KHR( + VkDevice device, + const VkBufferMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR( + VkDevice device, + const VkImageSparseMemoryRequirementsInfo2* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +#endif + +#define VK_KHR_image_format_list 1 +#define VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION 1 +#define VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME "VK_KHR_image_format_list" + +typedef struct VkImageFormatListCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t viewFormatCount; + const VkFormat* pViewFormats; +} VkImageFormatListCreateInfoKHR; + + + +#define VK_KHR_sampler_ycbcr_conversion 1 +typedef VkSamplerYcbcrConversion VkSamplerYcbcrConversionKHR; + + +#define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 1 +#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion" + +typedef VkSamplerYcbcrModelConversion VkSamplerYcbcrModelConversionKHR; + +typedef VkSamplerYcbcrRange VkSamplerYcbcrRangeKHR; + +typedef VkChromaLocation VkChromaLocationKHR; + + +typedef VkSamplerYcbcrConversionCreateInfo VkSamplerYcbcrConversionCreateInfoKHR; + +typedef VkSamplerYcbcrConversionInfo VkSamplerYcbcrConversionInfoKHR; + +typedef VkBindImagePlaneMemoryInfo VkBindImagePlaneMemoryInfoKHR; + +typedef VkImagePlaneMemoryRequirementsInfo VkImagePlaneMemoryRequirementsInfoKHR; + +typedef VkPhysicalDeviceSamplerYcbcrConversionFeatures VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR; + +typedef VkSamplerYcbcrConversionImageFormatProperties VkSamplerYcbcrConversionImageFormatPropertiesKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion); +typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversionKHR( + VkDevice device, + const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSamplerYcbcrConversion* pYcbcrConversion); + +VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR( + VkDevice device, + VkSamplerYcbcrConversion ycbcrConversion, + const VkAllocationCallbacks* pAllocator); +#endif + +#define VK_KHR_bind_memory2 1 +#define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1 +#define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2" + +typedef VkBindBufferMemoryInfo VkBindBufferMemoryInfoKHR; + +typedef VkBindImageMemoryInfo VkBindImageMemoryInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos); +typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2KHR( + VkDevice device, + uint32_t bindInfoCount, + const VkBindBufferMemoryInfo* pBindInfos); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR( + VkDevice device, + uint32_t bindInfoCount, + const VkBindImageMemoryInfo* pBindInfos); +#endif + +#define VK_KHR_maintenance3 1 +#define VK_KHR_MAINTENANCE3_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3" + +typedef VkPhysicalDeviceMaintenance3Properties VkPhysicalDeviceMaintenance3PropertiesKHR; + +typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR; + + +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupportKHR)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupportKHR( + VkDevice device, + const VkDescriptorSetLayoutCreateInfo* pCreateInfo, + VkDescriptorSetLayoutSupport* pSupport); +#endif + +#define VK_EXT_debug_report 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) + +#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 9 +#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report" +#define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT +#define VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT + + +typedef enum VkDebugReportObjectTypeEXT { + VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0, + VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT = 1, + VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT = 2, + VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT = 3, + VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT = 4, + VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT = 5, + VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT = 6, + VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT = 7, + VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT = 8, + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT = 9, + VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT = 10, + VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT = 11, + VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT = 12, + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT = 13, + VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT = 14, + VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT = 15, + VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT = 16, + VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT = 17, + VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT = 18, + VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT = 19, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT = 20, + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT = 21, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT = 22, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT = 23, + VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT = 24, + VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT = 25, + VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26, + VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27, + VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28, + VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29, + VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30, + VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31, + VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32, + VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33, + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1), + VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugReportObjectTypeEXT; + + +typedef enum VkDebugReportFlagBitsEXT { + VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0x00000001, + VK_DEBUG_REPORT_WARNING_BIT_EXT = 0x00000002, + VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0x00000004, + VK_DEBUG_REPORT_ERROR_BIT_EXT = 0x00000008, + VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0x00000010, + VK_DEBUG_REPORT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugReportFlagBitsEXT; +typedef VkFlags VkDebugReportFlagsEXT; + +typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)( + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage, + void* pUserData); + +typedef struct VkDebugReportCallbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugReportFlagsEXT flags; + PFN_vkDebugReportCallbackEXT pfnCallback; + void* pUserData; +} VkDebugReportCallbackCreateInfoEXT; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback); +typedef void (VKAPI_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDebugReportMessageEXT)(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT( + VkInstance instance, + const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDebugReportCallbackEXT* pCallback); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT( + VkInstance instance, + VkDebugReportCallbackEXT callback, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT( + VkInstance instance, + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage); +#endif + +#define VK_NV_glsl_shader 1 +#define VK_NV_GLSL_SHADER_SPEC_VERSION 1 +#define VK_NV_GLSL_SHADER_EXTENSION_NAME "VK_NV_glsl_shader" + + +#define VK_EXT_depth_range_unrestricted 1 +#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION 1 +#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME "VK_EXT_depth_range_unrestricted" + + +#define VK_IMG_filter_cubic 1 +#define VK_IMG_FILTER_CUBIC_SPEC_VERSION 1 +#define VK_IMG_FILTER_CUBIC_EXTENSION_NAME "VK_IMG_filter_cubic" + + +#define VK_AMD_rasterization_order 1 +#define VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION 1 +#define VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME "VK_AMD_rasterization_order" + + +typedef enum VkRasterizationOrderAMD { + VK_RASTERIZATION_ORDER_STRICT_AMD = 0, + VK_RASTERIZATION_ORDER_RELAXED_AMD = 1, + VK_RASTERIZATION_ORDER_BEGIN_RANGE_AMD = VK_RASTERIZATION_ORDER_STRICT_AMD, + VK_RASTERIZATION_ORDER_END_RANGE_AMD = VK_RASTERIZATION_ORDER_RELAXED_AMD, + VK_RASTERIZATION_ORDER_RANGE_SIZE_AMD = (VK_RASTERIZATION_ORDER_RELAXED_AMD - VK_RASTERIZATION_ORDER_STRICT_AMD + 1), + VK_RASTERIZATION_ORDER_MAX_ENUM_AMD = 0x7FFFFFFF +} VkRasterizationOrderAMD; + +typedef struct VkPipelineRasterizationStateRasterizationOrderAMD { + VkStructureType sType; + const void* pNext; + VkRasterizationOrderAMD rasterizationOrder; +} VkPipelineRasterizationStateRasterizationOrderAMD; + + + +#define VK_AMD_shader_trinary_minmax 1 +#define VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION 1 +#define VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME "VK_AMD_shader_trinary_minmax" + + +#define VK_AMD_shader_explicit_vertex_parameter 1 +#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION 1 +#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter" + + +#define VK_EXT_debug_marker 1 +#define VK_EXT_DEBUG_MARKER_SPEC_VERSION 4 +#define VK_EXT_DEBUG_MARKER_EXTENSION_NAME "VK_EXT_debug_marker" + +typedef struct VkDebugMarkerObjectNameInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugReportObjectTypeEXT objectType; + uint64_t object; + const char* pObjectName; +} VkDebugMarkerObjectNameInfoEXT; + +typedef struct VkDebugMarkerObjectTagInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugReportObjectTypeEXT objectType; + uint64_t object; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkDebugMarkerObjectTagInfoEXT; + +typedef struct VkDebugMarkerMarkerInfoEXT { + VkStructureType sType; + const void* pNext; + const char* pMarkerName; + float color[4]; +} VkDebugMarkerMarkerInfoEXT; + + +typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectTagEXT)(VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo); +typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectNameEXT)(VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerBeginEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerEndEXT)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerInsertEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectTagEXT( + VkDevice device, + const VkDebugMarkerObjectTagInfoEXT* pTagInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectNameEXT( + VkDevice device, + const VkDebugMarkerObjectNameInfoEXT* pNameInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerBeginEXT( + VkCommandBuffer commandBuffer, + const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerEndEXT( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT( + VkCommandBuffer commandBuffer, + const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); +#endif + +#define VK_AMD_gcn_shader 1 +#define VK_AMD_GCN_SHADER_SPEC_VERSION 1 +#define VK_AMD_GCN_SHADER_EXTENSION_NAME "VK_AMD_gcn_shader" + + +#define VK_NV_dedicated_allocation 1 +#define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1 +#define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation" + +typedef struct VkDedicatedAllocationImageCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 dedicatedAllocation; +} VkDedicatedAllocationImageCreateInfoNV; + +typedef struct VkDedicatedAllocationBufferCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 dedicatedAllocation; +} VkDedicatedAllocationBufferCreateInfoNV; + +typedef struct VkDedicatedAllocationMemoryAllocateInfoNV { + VkStructureType sType; + const void* pNext; + VkImage image; + VkBuffer buffer; +} VkDedicatedAllocationMemoryAllocateInfoNV; + + + +#define VK_AMD_draw_indirect_count 1 +#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 1 +#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count" + +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif + +#define VK_AMD_negative_viewport_height 1 +#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1 +#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height" + + +#define VK_AMD_gpu_shader_half_float 1 +#define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 1 +#define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float" + + +#define VK_AMD_shader_ballot 1 +#define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1 +#define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot" + + +#define VK_AMD_texture_gather_bias_lod 1 +#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION 1 +#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod" + +typedef struct VkTextureLODGatherFormatPropertiesAMD { + VkStructureType sType; + void* pNext; + VkBool32 supportsTextureGatherLODBiasAMD; +} VkTextureLODGatherFormatPropertiesAMD; + + + +#define VK_AMD_shader_info 1 +#define VK_AMD_SHADER_INFO_SPEC_VERSION 1 +#define VK_AMD_SHADER_INFO_EXTENSION_NAME "VK_AMD_shader_info" + + +typedef enum VkShaderInfoTypeAMD { + VK_SHADER_INFO_TYPE_STATISTICS_AMD = 0, + VK_SHADER_INFO_TYPE_BINARY_AMD = 1, + VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD = 2, + VK_SHADER_INFO_TYPE_BEGIN_RANGE_AMD = VK_SHADER_INFO_TYPE_STATISTICS_AMD, + VK_SHADER_INFO_TYPE_END_RANGE_AMD = VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD, + VK_SHADER_INFO_TYPE_RANGE_SIZE_AMD = (VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD - VK_SHADER_INFO_TYPE_STATISTICS_AMD + 1), + VK_SHADER_INFO_TYPE_MAX_ENUM_AMD = 0x7FFFFFFF +} VkShaderInfoTypeAMD; + +typedef struct VkShaderResourceUsageAMD { + uint32_t numUsedVgprs; + uint32_t numUsedSgprs; + uint32_t ldsSizePerLocalWorkGroup; + size_t ldsUsageSizeInBytes; + size_t scratchMemUsageInBytes; +} VkShaderResourceUsageAMD; + +typedef struct VkShaderStatisticsInfoAMD { + VkShaderStageFlags shaderStageMask; + VkShaderResourceUsageAMD resourceUsage; + uint32_t numPhysicalVgprs; + uint32_t numPhysicalSgprs; + uint32_t numAvailableVgprs; + uint32_t numAvailableSgprs; + uint32_t computeWorkGroupSize[3]; +} VkShaderStatisticsInfoAMD; + + +typedef VkResult (VKAPI_PTR *PFN_vkGetShaderInfoAMD)(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits shaderStage, VkShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD( + VkDevice device, + VkPipeline pipeline, + VkShaderStageFlagBits shaderStage, + VkShaderInfoTypeAMD infoType, + size_t* pInfoSize, + void* pInfo); +#endif + +#define VK_AMD_shader_image_load_store_lod 1 +#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1 +#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod" + + +#define VK_IMG_format_pvrtc 1 +#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1 +#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc" + + +#define VK_NV_external_memory_capabilities 1 +#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities" + + +typedef enum VkExternalMemoryHandleTypeFlagBitsNV { + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0x00000004, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkExternalMemoryHandleTypeFlagBitsNV; +typedef VkFlags VkExternalMemoryHandleTypeFlagsNV; + +typedef enum VkExternalMemoryFeatureFlagBitsNV { + VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0x00000001, + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0x00000002, + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0x00000004, + VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkExternalMemoryFeatureFlagBitsNV; +typedef VkFlags VkExternalMemoryFeatureFlagsNV; + +typedef struct VkExternalImageFormatPropertiesNV { + VkImageFormatProperties imageFormatProperties; + VkExternalMemoryFeatureFlagsNV externalMemoryFeatures; + VkExternalMemoryHandleTypeFlagsNV exportFromImportedHandleTypes; + VkExternalMemoryHandleTypeFlagsNV compatibleHandleTypes; +} VkExternalImageFormatPropertiesNV; + + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesNV( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags, + VkExternalMemoryHandleTypeFlagsNV externalHandleType, + VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); +#endif + +#define VK_NV_external_memory 1 +#define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory" + +typedef struct VkExternalMemoryImageCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagsNV handleTypes; +} VkExternalMemoryImageCreateInfoNV; + +typedef struct VkExportMemoryAllocateInfoNV { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagsNV handleTypes; +} VkExportMemoryAllocateInfoNV; + + + +#define VK_EXT_validation_flags 1 +#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1 +#define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags" + + +typedef enum VkValidationCheckEXT { + VK_VALIDATION_CHECK_ALL_EXT = 0, + VK_VALIDATION_CHECK_SHADERS_EXT = 1, + VK_VALIDATION_CHECK_BEGIN_RANGE_EXT = VK_VALIDATION_CHECK_ALL_EXT, + VK_VALIDATION_CHECK_END_RANGE_EXT = VK_VALIDATION_CHECK_SHADERS_EXT, + VK_VALIDATION_CHECK_RANGE_SIZE_EXT = (VK_VALIDATION_CHECK_SHADERS_EXT - VK_VALIDATION_CHECK_ALL_EXT + 1), + VK_VALIDATION_CHECK_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationCheckEXT; + +typedef struct VkValidationFlagsEXT { + VkStructureType sType; + const void* pNext; + uint32_t disabledValidationCheckCount; + VkValidationCheckEXT* pDisabledValidationChecks; +} VkValidationFlagsEXT; + + + +#define VK_EXT_shader_subgroup_ballot 1 +#define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1 +#define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot" + + +#define VK_EXT_shader_subgroup_vote 1 +#define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1 +#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote" + + +#define VK_NVX_device_generated_commands 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX) + +#define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 +#define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands" + + +typedef enum VkIndirectCommandsTokenTypeNVX { + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX = 0, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX = 1, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX = 2, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX = 3, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX = 4, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX = 5, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX = 6, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX = 7, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NVX = (VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX + 1), + VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF +} VkIndirectCommandsTokenTypeNVX; + +typedef enum VkObjectEntryTypeNVX { + VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX = 0, + VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX = 1, + VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX = 2, + VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX = 3, + VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX = 4, + VK_OBJECT_ENTRY_TYPE_BEGIN_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX, + VK_OBJECT_ENTRY_TYPE_END_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX, + VK_OBJECT_ENTRY_TYPE_RANGE_SIZE_NVX = (VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX - VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX + 1), + VK_OBJECT_ENTRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF +} VkObjectEntryTypeNVX; + + +typedef enum VkIndirectCommandsLayoutUsageFlagBitsNVX { + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX = 0x00000001, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX = 0x00000002, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX = 0x00000004, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX = 0x00000008, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF +} VkIndirectCommandsLayoutUsageFlagBitsNVX; +typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNVX; + +typedef enum VkObjectEntryUsageFlagBitsNVX { + VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX = 0x00000001, + VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX = 0x00000002, + VK_OBJECT_ENTRY_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF +} VkObjectEntryUsageFlagBitsNVX; +typedef VkFlags VkObjectEntryUsageFlagsNVX; + +typedef struct VkDeviceGeneratedCommandsFeaturesNVX { + VkStructureType sType; + const void* pNext; + VkBool32 computeBindingPointSupport; +} VkDeviceGeneratedCommandsFeaturesNVX; + +typedef struct VkDeviceGeneratedCommandsLimitsNVX { + VkStructureType sType; + const void* pNext; + uint32_t maxIndirectCommandsLayoutTokenCount; + uint32_t maxObjectEntryCounts; + uint32_t minSequenceCountBufferOffsetAlignment; + uint32_t minSequenceIndexBufferOffsetAlignment; + uint32_t minCommandsTokenBufferOffsetAlignment; +} VkDeviceGeneratedCommandsLimitsNVX; + +typedef struct VkIndirectCommandsTokenNVX { + VkIndirectCommandsTokenTypeNVX tokenType; + VkBuffer buffer; + VkDeviceSize offset; +} VkIndirectCommandsTokenNVX; + +typedef struct VkIndirectCommandsLayoutTokenNVX { + VkIndirectCommandsTokenTypeNVX tokenType; + uint32_t bindingUnit; + uint32_t dynamicCount; + uint32_t divisor; +} VkIndirectCommandsLayoutTokenNVX; + +typedef struct VkIndirectCommandsLayoutCreateInfoNVX { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkIndirectCommandsLayoutUsageFlagsNVX flags; + uint32_t tokenCount; + const VkIndirectCommandsLayoutTokenNVX* pTokens; +} VkIndirectCommandsLayoutCreateInfoNVX; + +typedef struct VkCmdProcessCommandsInfoNVX { + VkStructureType sType; + const void* pNext; + VkObjectTableNVX objectTable; + VkIndirectCommandsLayoutNVX indirectCommandsLayout; + uint32_t indirectCommandsTokenCount; + const VkIndirectCommandsTokenNVX* pIndirectCommandsTokens; + uint32_t maxSequencesCount; + VkCommandBuffer targetCommandBuffer; + VkBuffer sequencesCountBuffer; + VkDeviceSize sequencesCountOffset; + VkBuffer sequencesIndexBuffer; + VkDeviceSize sequencesIndexOffset; +} VkCmdProcessCommandsInfoNVX; + +typedef struct VkCmdReserveSpaceForCommandsInfoNVX { + VkStructureType sType; + const void* pNext; + VkObjectTableNVX objectTable; + VkIndirectCommandsLayoutNVX indirectCommandsLayout; + uint32_t maxSequencesCount; +} VkCmdReserveSpaceForCommandsInfoNVX; + +typedef struct VkObjectTableCreateInfoNVX { + VkStructureType sType; + const void* pNext; + uint32_t objectCount; + const VkObjectEntryTypeNVX* pObjectEntryTypes; + const uint32_t* pObjectEntryCounts; + const VkObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags; + uint32_t maxUniformBuffersPerDescriptor; + uint32_t maxStorageBuffersPerDescriptor; + uint32_t maxStorageImagesPerDescriptor; + uint32_t maxSampledImagesPerDescriptor; + uint32_t maxPipelineLayouts; +} VkObjectTableCreateInfoNVX; + +typedef struct VkObjectTableEntryNVX { + VkObjectEntryTypeNVX type; + VkObjectEntryUsageFlagsNVX flags; +} VkObjectTableEntryNVX; + +typedef struct VkObjectTablePipelineEntryNVX { + VkObjectEntryTypeNVX type; + VkObjectEntryUsageFlagsNVX flags; + VkPipeline pipeline; +} VkObjectTablePipelineEntryNVX; + +typedef struct VkObjectTableDescriptorSetEntryNVX { + VkObjectEntryTypeNVX type; + VkObjectEntryUsageFlagsNVX flags; + VkPipelineLayout pipelineLayout; + VkDescriptorSet descriptorSet; +} VkObjectTableDescriptorSetEntryNVX; + +typedef struct VkObjectTableVertexBufferEntryNVX { + VkObjectEntryTypeNVX type; + VkObjectEntryUsageFlagsNVX flags; + VkBuffer buffer; +} VkObjectTableVertexBufferEntryNVX; + +typedef struct VkObjectTableIndexBufferEntryNVX { + VkObjectEntryTypeNVX type; + VkObjectEntryUsageFlagsNVX flags; + VkBuffer buffer; + VkIndexType indexType; +} VkObjectTableIndexBufferEntryNVX; + +typedef struct VkObjectTablePushConstantEntryNVX { + VkObjectEntryTypeNVX type; + VkObjectEntryUsageFlagsNVX flags; + VkPipelineLayout pipelineLayout; + VkShaderStageFlags stageFlags; +} VkObjectTablePushConstantEntryNVX; + + +typedef void (VKAPI_PTR *PFN_vkCmdProcessCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdReserveSpaceForCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNVX)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNVX)(VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateObjectTableNVX)(VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable); +typedef void (VKAPI_PTR *PFN_vkDestroyObjectTableNVX)(VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkRegisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices); +typedef VkResult (VKAPI_PTR *PFN_vkUnregisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)(VkPhysicalDevice physicalDevice, VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, VkDeviceGeneratedCommandsLimitsNVX* pLimits); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdProcessCommandsNVX( + VkCommandBuffer commandBuffer, + const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdReserveSpaceForCommandsNVX( + VkCommandBuffer commandBuffer, + const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNVX( + VkDevice device, + const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout); + +VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNVX( + VkDevice device, + VkIndirectCommandsLayoutNVX indirectCommandsLayout, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateObjectTableNVX( + VkDevice device, + const VkObjectTableCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkObjectTableNVX* pObjectTable); + +VKAPI_ATTR void VKAPI_CALL vkDestroyObjectTableNVX( + VkDevice device, + VkObjectTableNVX objectTable, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkRegisterObjectsNVX( + VkDevice device, + VkObjectTableNVX objectTable, + uint32_t objectCount, + const VkObjectTableEntryNVX* const* ppObjectTableEntries, + const uint32_t* pObjectIndices); + +VKAPI_ATTR VkResult VKAPI_CALL vkUnregisterObjectsNVX( + VkDevice device, + VkObjectTableNVX objectTable, + uint32_t objectCount, + const VkObjectEntryTypeNVX* pObjectEntryTypes, + const uint32_t* pObjectIndices); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( + VkPhysicalDevice physicalDevice, + VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, + VkDeviceGeneratedCommandsLimitsNVX* pLimits); +#endif + +#define VK_NV_clip_space_w_scaling 1 +#define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1 +#define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling" + +typedef struct VkViewportWScalingNV { + float xcoeff; + float ycoeff; +} VkViewportWScalingNV; + +typedef struct VkPipelineViewportWScalingStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 viewportWScalingEnable; + uint32_t viewportCount; + const VkViewportWScalingNV* pViewportWScalings; +} VkPipelineViewportWScalingStateCreateInfoNV; + + +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewportWScalingNV* pViewportWScalings); +#endif + +#define VK_EXT_direct_mode_display 1 +#define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1 +#define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display" + +typedef VkResult (VKAPI_PTR *PFN_vkReleaseDisplayEXT)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display); +#endif + +#define VK_EXT_display_surface_counter 1 +#define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1 +#define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter" +#define VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT + + +typedef enum VkSurfaceCounterFlagBitsEXT { + VK_SURFACE_COUNTER_VBLANK_EXT = 0x00000001, + VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkSurfaceCounterFlagBitsEXT; +typedef VkFlags VkSurfaceCounterFlagsEXT; + +typedef struct VkSurfaceCapabilities2EXT { + VkStructureType sType; + void* pNext; + uint32_t minImageCount; + uint32_t maxImageCount; + VkExtent2D currentExtent; + VkExtent2D minImageExtent; + VkExtent2D maxImageExtent; + uint32_t maxImageArrayLayers; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkSurfaceTransformFlagBitsKHR currentTransform; + VkCompositeAlphaFlagsKHR supportedCompositeAlpha; + VkImageUsageFlags supportedUsageFlags; + VkSurfaceCounterFlagsEXT supportedSurfaceCounters; +} VkSurfaceCapabilities2EXT; + + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + VkSurfaceCapabilities2EXT* pSurfaceCapabilities); +#endif + +#define VK_EXT_display_control 1 +#define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1 +#define VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME "VK_EXT_display_control" + + +typedef enum VkDisplayPowerStateEXT { + VK_DISPLAY_POWER_STATE_OFF_EXT = 0, + VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1, + VK_DISPLAY_POWER_STATE_ON_EXT = 2, + VK_DISPLAY_POWER_STATE_BEGIN_RANGE_EXT = VK_DISPLAY_POWER_STATE_OFF_EXT, + VK_DISPLAY_POWER_STATE_END_RANGE_EXT = VK_DISPLAY_POWER_STATE_ON_EXT, + VK_DISPLAY_POWER_STATE_RANGE_SIZE_EXT = (VK_DISPLAY_POWER_STATE_ON_EXT - VK_DISPLAY_POWER_STATE_OFF_EXT + 1), + VK_DISPLAY_POWER_STATE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDisplayPowerStateEXT; + +typedef enum VkDeviceEventTypeEXT { + VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0, + VK_DEVICE_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT, + VK_DEVICE_EVENT_TYPE_END_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT, + VK_DEVICE_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT - VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT + 1), + VK_DEVICE_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceEventTypeEXT; + +typedef enum VkDisplayEventTypeEXT { + VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0, + VK_DISPLAY_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT, + VK_DISPLAY_EVENT_TYPE_END_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT, + VK_DISPLAY_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT - VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT + 1), + VK_DISPLAY_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDisplayEventTypeEXT; + +typedef struct VkDisplayPowerInfoEXT { + VkStructureType sType; + const void* pNext; + VkDisplayPowerStateEXT powerState; +} VkDisplayPowerInfoEXT; + +typedef struct VkDeviceEventInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceEventTypeEXT deviceEvent; +} VkDeviceEventInfoEXT; + +typedef struct VkDisplayEventInfoEXT { + VkStructureType sType; + const void* pNext; + VkDisplayEventTypeEXT displayEvent; +} VkDisplayEventInfoEXT; + +typedef struct VkSwapchainCounterCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkSurfaceCounterFlagsEXT surfaceCounters; +} VkSwapchainCounterCreateInfoEXT; + + +typedef VkResult (VKAPI_PTR *PFN_vkDisplayPowerControlEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo); +typedef VkResult (VKAPI_PTR *PFN_vkRegisterDeviceEventEXT)(VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +typedef VkResult (VKAPI_PTR *PFN_vkRegisterDisplayEventEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainCounterEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkDisplayPowerControlEXT( + VkDevice device, + VkDisplayKHR display, + const VkDisplayPowerInfoEXT* pDisplayPowerInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDeviceEventEXT( + VkDevice device, + const VkDeviceEventInfoEXT* pDeviceEventInfo, + const VkAllocationCallbacks* pAllocator, + VkFence* pFence); + +VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDisplayEventEXT( + VkDevice device, + VkDisplayKHR display, + const VkDisplayEventInfoEXT* pDisplayEventInfo, + const VkAllocationCallbacks* pAllocator, + VkFence* pFence); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT( + VkDevice device, + VkSwapchainKHR swapchain, + VkSurfaceCounterFlagBitsEXT counter, + uint64_t* pCounterValue); +#endif + +#define VK_GOOGLE_display_timing 1 +#define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1 +#define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing" + +typedef struct VkRefreshCycleDurationGOOGLE { + uint64_t refreshDuration; +} VkRefreshCycleDurationGOOGLE; + +typedef struct VkPastPresentationTimingGOOGLE { + uint32_t presentID; + uint64_t desiredPresentTime; + uint64_t actualPresentTime; + uint64_t earliestPresentTime; + uint64_t presentMargin; +} VkPastPresentationTimingGOOGLE; + +typedef struct VkPresentTimeGOOGLE { + uint32_t presentID; + uint64_t desiredPresentTime; +} VkPresentTimeGOOGLE; + +typedef struct VkPresentTimesInfoGOOGLE { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentTimeGOOGLE* pTimes; +} VkPresentTimesInfoGOOGLE; + + +typedef VkResult (VKAPI_PTR *PFN_vkGetRefreshCycleDurationGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetRefreshCycleDurationGOOGLE( + VkDevice device, + VkSwapchainKHR swapchain, + VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t* pPresentationTimingCount, + VkPastPresentationTimingGOOGLE* pPresentationTimings); +#endif + +#define VK_NV_sample_mask_override_coverage 1 +#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1 +#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage" + + +#define VK_NV_geometry_shader_passthrough 1 +#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1 +#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough" + + +#define VK_NV_viewport_array2 1 +#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION 1 +#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME "VK_NV_viewport_array2" + + +#define VK_NVX_multiview_per_view_attributes 1 +#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1 +#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes" + +typedef struct VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX { + VkStructureType sType; + void* pNext; + VkBool32 perViewPositionAllComponents; +} VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX; + + + +#define VK_NV_viewport_swizzle 1 +#define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1 +#define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle" + + +typedef enum VkViewportCoordinateSwizzleNV { + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0, + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1, + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV = 2, + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV = 3, + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV = 4, + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5, + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6, + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7, + VK_VIEWPORT_COORDINATE_SWIZZLE_BEGIN_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, + VK_VIEWPORT_COORDINATE_SWIZZLE_END_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV, + VK_VIEWPORT_COORDINATE_SWIZZLE_RANGE_SIZE_NV = (VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV + 1), + VK_VIEWPORT_COORDINATE_SWIZZLE_MAX_ENUM_NV = 0x7FFFFFFF +} VkViewportCoordinateSwizzleNV; + +typedef VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV; + +typedef struct VkViewportSwizzleNV { + VkViewportCoordinateSwizzleNV x; + VkViewportCoordinateSwizzleNV y; + VkViewportCoordinateSwizzleNV z; + VkViewportCoordinateSwizzleNV w; +} VkViewportSwizzleNV; + +typedef struct VkPipelineViewportSwizzleStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineViewportSwizzleStateCreateFlagsNV flags; + uint32_t viewportCount; + const VkViewportSwizzleNV* pViewportSwizzles; +} VkPipelineViewportSwizzleStateCreateInfoNV; + + + +#define VK_EXT_discard_rectangles 1 +#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1 +#define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles" + + +typedef enum VkDiscardRectangleModeEXT { + VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0, + VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1, + VK_DISCARD_RECTANGLE_MODE_BEGIN_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT, + VK_DISCARD_RECTANGLE_MODE_END_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT, + VK_DISCARD_RECTANGLE_MODE_RANGE_SIZE_EXT = (VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT - VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT + 1), + VK_DISCARD_RECTANGLE_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDiscardRectangleModeEXT; + +typedef VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT; + +typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxDiscardRectangles; +} VkPhysicalDeviceDiscardRectanglePropertiesEXT; + +typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineDiscardRectangleStateCreateFlagsEXT flags; + VkDiscardRectangleModeEXT discardRectangleMode; + uint32_t discardRectangleCount; + const VkRect2D* pDiscardRectangles; +} VkPipelineDiscardRectangleStateCreateInfoEXT; + + +typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEXT)(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT( + VkCommandBuffer commandBuffer, + uint32_t firstDiscardRectangle, + uint32_t discardRectangleCount, + const VkRect2D* pDiscardRectangles); +#endif + +#define VK_EXT_conservative_rasterization 1 +#define VK_EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION 1 +#define VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME "VK_EXT_conservative_rasterization" + + +typedef enum VkConservativeRasterizationModeEXT { + VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT = 0, + VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT = 1, + VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT = 2, + VK_CONSERVATIVE_RASTERIZATION_MODE_BEGIN_RANGE_EXT = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT, + VK_CONSERVATIVE_RASTERIZATION_MODE_END_RANGE_EXT = VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT, + VK_CONSERVATIVE_RASTERIZATION_MODE_RANGE_SIZE_EXT = (VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT - VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT + 1), + VK_CONSERVATIVE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkConservativeRasterizationModeEXT; + +typedef VkFlags VkPipelineRasterizationConservativeStateCreateFlagsEXT; + +typedef struct VkPhysicalDeviceConservativeRasterizationPropertiesEXT { + VkStructureType sType; + void* pNext; + float primitiveOverestimationSize; + float maxExtraPrimitiveOverestimationSize; + float extraPrimitiveOverestimationSizeGranularity; + VkBool32 primitiveUnderestimation; + VkBool32 conservativePointAndLineRasterization; + VkBool32 degenerateTrianglesRasterized; + VkBool32 degenerateLinesRasterized; + VkBool32 fullyCoveredFragmentShaderInputVariable; + VkBool32 conservativeRasterizationPostDepthCoverage; +} VkPhysicalDeviceConservativeRasterizationPropertiesEXT; + +typedef struct VkPipelineRasterizationConservativeStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationConservativeStateCreateFlagsEXT flags; + VkConservativeRasterizationModeEXT conservativeRasterizationMode; + float extraPrimitiveOverestimationSize; +} VkPipelineRasterizationConservativeStateCreateInfoEXT; + + + +#define VK_EXT_swapchain_colorspace 1 +#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 3 +#define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace" + + +#define VK_EXT_hdr_metadata 1 +#define VK_EXT_HDR_METADATA_SPEC_VERSION 1 +#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata" + +typedef struct VkXYColorEXT { + float x; + float y; +} VkXYColorEXT; + +typedef struct VkHdrMetadataEXT { + VkStructureType sType; + const void* pNext; + VkXYColorEXT displayPrimaryRed; + VkXYColorEXT displayPrimaryGreen; + VkXYColorEXT displayPrimaryBlue; + VkXYColorEXT whitePoint; + float maxLuminance; + float minLuminance; + float maxContentLightLevel; + float maxFrameAverageLightLevel; +} VkHdrMetadataEXT; + + +typedef void (VKAPI_PTR *PFN_vkSetHdrMetadataEXT)(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( + VkDevice device, + uint32_t swapchainCount, + const VkSwapchainKHR* pSwapchains, + const VkHdrMetadataEXT* pMetadata); +#endif + +#define VK_EXT_external_memory_dma_buf 1 +#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION 1 +#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME "VK_EXT_external_memory_dma_buf" + + +#define VK_EXT_queue_family_foreign 1 +#define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1 +#define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME "VK_EXT_queue_family_foreign" +#define VK_QUEUE_FAMILY_FOREIGN_EXT (~0U-2) + + +#define VK_EXT_debug_utils 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugUtilsMessengerEXT) + +#define VK_EXT_DEBUG_UTILS_SPEC_VERSION 1 +#define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils" + +typedef VkFlags VkDebugUtilsMessengerCallbackDataFlagsEXT; +typedef VkFlags VkDebugUtilsMessengerCreateFlagsEXT; + +typedef enum VkDebugUtilsMessageSeverityFlagBitsEXT { + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugUtilsMessageSeverityFlagBitsEXT; +typedef VkFlags VkDebugUtilsMessageSeverityFlagsEXT; + +typedef enum VkDebugUtilsMessageTypeFlagBitsEXT { + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001, + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002, + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004, + VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugUtilsMessageTypeFlagBitsEXT; +typedef VkFlags VkDebugUtilsMessageTypeFlagsEXT; + +typedef struct VkDebugUtilsObjectNameInfoEXT { + VkStructureType sType; + const void* pNext; + VkObjectType objectType; + uint64_t objectHandle; + const char* pObjectName; +} VkDebugUtilsObjectNameInfoEXT; + +typedef struct VkDebugUtilsObjectTagInfoEXT { + VkStructureType sType; + const void* pNext; + VkObjectType objectType; + uint64_t objectHandle; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkDebugUtilsObjectTagInfoEXT; + +typedef struct VkDebugUtilsLabelEXT { + VkStructureType sType; + const void* pNext; + const char* pLabelName; + float color[4]; +} VkDebugUtilsLabelEXT; + +typedef struct VkDebugUtilsMessengerCallbackDataEXT { + VkStructureType sType; + const void* pNext; + VkDebugUtilsMessengerCallbackDataFlagsEXT flags; + const char* pMessageIdName; + int32_t messageIdNumber; + const char* pMessage; + uint32_t queueLabelCount; + VkDebugUtilsLabelEXT* pQueueLabels; + uint32_t cmdBufLabelCount; + VkDebugUtilsLabelEXT* pCmdBufLabels; + uint32_t objectCount; + VkDebugUtilsObjectNameInfoEXT* pObjects; +} VkDebugUtilsMessengerCallbackDataEXT; + +typedef VkBool32 (VKAPI_PTR *PFN_vkDebugUtilsMessengerCallbackEXT)( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData); + +typedef struct VkDebugUtilsMessengerCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugUtilsMessengerCreateFlagsEXT flags; + VkDebugUtilsMessageSeverityFlagsEXT messageSeverity; + VkDebugUtilsMessageTypeFlagsEXT messageType; + PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback; + void* pUserData; +} VkDebugUtilsMessengerCreateInfoEXT; + + +typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectNameEXT)(VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo); +typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectTagEXT)(VkDevice device, const VkDebugUtilsObjectTagInfoEXT* pTagInfo); +typedef void (VKAPI_PTR *PFN_vkQueueBeginDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef void (VKAPI_PTR *PFN_vkQueueEndDebugUtilsLabelEXT)(VkQueue queue); +typedef void (VKAPI_PTR *PFN_vkQueueInsertDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBeginDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdInsertDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugUtilsMessengerEXT)(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger); +typedef void (VKAPI_PTR *PFN_vkDestroyDebugUtilsMessengerEXT)(VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkSubmitDebugUtilsMessageEXT)(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectNameEXT( + VkDevice device, + const VkDebugUtilsObjectNameInfoEXT* pNameInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectTagEXT( + VkDevice device, + const VkDebugUtilsObjectTagInfoEXT* pTagInfo); + +VKAPI_ATTR void VKAPI_CALL vkQueueBeginDebugUtilsLabelEXT( + VkQueue queue, + const VkDebugUtilsLabelEXT* pLabelInfo); + +VKAPI_ATTR void VKAPI_CALL vkQueueEndDebugUtilsLabelEXT( + VkQueue queue); + +VKAPI_ATTR void VKAPI_CALL vkQueueInsertDebugUtilsLabelEXT( + VkQueue queue, + const VkDebugUtilsLabelEXT* pLabelInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginDebugUtilsLabelEXT( + VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT* pLabelInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndDebugUtilsLabelEXT( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR void VKAPI_CALL vkCmdInsertDebugUtilsLabelEXT( + VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT* pLabelInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT( + VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDebugUtilsMessengerEXT* pMessenger); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT( + VkInstance instance, + VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkSubmitDebugUtilsMessageEXT( + VkInstance instance, + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); +#endif + +#define VK_EXT_sampler_filter_minmax 1 +#define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 1 +#define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME "VK_EXT_sampler_filter_minmax" + + +typedef enum VkSamplerReductionModeEXT { + VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT = 0, + VK_SAMPLER_REDUCTION_MODE_MIN_EXT = 1, + VK_SAMPLER_REDUCTION_MODE_MAX_EXT = 2, + VK_SAMPLER_REDUCTION_MODE_BEGIN_RANGE_EXT = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT, + VK_SAMPLER_REDUCTION_MODE_END_RANGE_EXT = VK_SAMPLER_REDUCTION_MODE_MAX_EXT, + VK_SAMPLER_REDUCTION_MODE_RANGE_SIZE_EXT = (VK_SAMPLER_REDUCTION_MODE_MAX_EXT - VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT + 1), + VK_SAMPLER_REDUCTION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkSamplerReductionModeEXT; + +typedef struct VkSamplerReductionModeCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkSamplerReductionModeEXT reductionMode; +} VkSamplerReductionModeCreateInfoEXT; + +typedef struct VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 filterMinmaxSingleComponentFormats; + VkBool32 filterMinmaxImageComponentMapping; +} VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT; + + + +#define VK_AMD_gpu_shader_int16 1 +#define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 1 +#define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16" + + +#define VK_AMD_mixed_attachment_samples 1 +#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION 1 +#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME "VK_AMD_mixed_attachment_samples" + + +#define VK_AMD_shader_fragment_mask 1 +#define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1 +#define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask" + + +#define VK_EXT_shader_stencil_export 1 +#define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1 +#define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export" + + +#define VK_EXT_sample_locations 1 +#define VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION 1 +#define VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME "VK_EXT_sample_locations" + +typedef struct VkSampleLocationEXT { + float x; + float y; +} VkSampleLocationEXT; + +typedef struct VkSampleLocationsInfoEXT { + VkStructureType sType; + const void* pNext; + VkSampleCountFlagBits sampleLocationsPerPixel; + VkExtent2D sampleLocationGridSize; + uint32_t sampleLocationsCount; + const VkSampleLocationEXT* pSampleLocations; +} VkSampleLocationsInfoEXT; + +typedef struct VkAttachmentSampleLocationsEXT { + uint32_t attachmentIndex; + VkSampleLocationsInfoEXT sampleLocationsInfo; +} VkAttachmentSampleLocationsEXT; + +typedef struct VkSubpassSampleLocationsEXT { + uint32_t subpassIndex; + VkSampleLocationsInfoEXT sampleLocationsInfo; +} VkSubpassSampleLocationsEXT; + +typedef struct VkRenderPassSampleLocationsBeginInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t attachmentInitialSampleLocationsCount; + const VkAttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations; + uint32_t postSubpassSampleLocationsCount; + const VkSubpassSampleLocationsEXT* pPostSubpassSampleLocations; +} VkRenderPassSampleLocationsBeginInfoEXT; + +typedef struct VkPipelineSampleLocationsStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 sampleLocationsEnable; + VkSampleLocationsInfoEXT sampleLocationsInfo; +} VkPipelineSampleLocationsStateCreateInfoEXT; + +typedef struct VkPhysicalDeviceSampleLocationsPropertiesEXT { + VkStructureType sType; + void* pNext; + VkSampleCountFlags sampleLocationSampleCounts; + VkExtent2D maxSampleLocationGridSize; + float sampleLocationCoordinateRange[2]; + uint32_t sampleLocationSubPixelBits; + VkBool32 variableSampleLocations; +} VkPhysicalDeviceSampleLocationsPropertiesEXT; + +typedef struct VkMultisamplePropertiesEXT { + VkStructureType sType; + void* pNext; + VkExtent2D maxSampleLocationGridSize; +} VkMultisamplePropertiesEXT; + + +typedef void (VKAPI_PTR *PFN_vkCmdSetSampleLocationsEXT)(VkCommandBuffer commandBuffer, const VkSampleLocationsInfoEXT* pSampleLocationsInfo); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)(VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleLocationsEXT( + VkCommandBuffer commandBuffer, + const VkSampleLocationsInfoEXT* pSampleLocationsInfo); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMultisamplePropertiesEXT( + VkPhysicalDevice physicalDevice, + VkSampleCountFlagBits samples, + VkMultisamplePropertiesEXT* pMultisampleProperties); +#endif + +#define VK_EXT_blend_operation_advanced 1 +#define VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION 2 +#define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME "VK_EXT_blend_operation_advanced" + + +typedef enum VkBlendOverlapEXT { + VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0, + VK_BLEND_OVERLAP_DISJOINT_EXT = 1, + VK_BLEND_OVERLAP_CONJOINT_EXT = 2, + VK_BLEND_OVERLAP_BEGIN_RANGE_EXT = VK_BLEND_OVERLAP_UNCORRELATED_EXT, + VK_BLEND_OVERLAP_END_RANGE_EXT = VK_BLEND_OVERLAP_CONJOINT_EXT, + VK_BLEND_OVERLAP_RANGE_SIZE_EXT = (VK_BLEND_OVERLAP_CONJOINT_EXT - VK_BLEND_OVERLAP_UNCORRELATED_EXT + 1), + VK_BLEND_OVERLAP_MAX_ENUM_EXT = 0x7FFFFFFF +} VkBlendOverlapEXT; + +typedef struct VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 advancedBlendCoherentOperations; +} VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT; + +typedef struct VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t advancedBlendMaxColorAttachments; + VkBool32 advancedBlendIndependentBlend; + VkBool32 advancedBlendNonPremultipliedSrcColor; + VkBool32 advancedBlendNonPremultipliedDstColor; + VkBool32 advancedBlendCorrelatedOverlap; + VkBool32 advancedBlendAllOperations; +} VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT; + +typedef struct VkPipelineColorBlendAdvancedStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 srcPremultiplied; + VkBool32 dstPremultiplied; + VkBlendOverlapEXT blendOverlap; +} VkPipelineColorBlendAdvancedStateCreateInfoEXT; + + + +#define VK_NV_fragment_coverage_to_color 1 +#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME "VK_NV_fragment_coverage_to_color" + +typedef VkFlags VkPipelineCoverageToColorStateCreateFlagsNV; + +typedef struct VkPipelineCoverageToColorStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCoverageToColorStateCreateFlagsNV flags; + VkBool32 coverageToColorEnable; + uint32_t coverageToColorLocation; +} VkPipelineCoverageToColorStateCreateInfoNV; + + + +#define VK_NV_framebuffer_mixed_samples 1 +#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION 1 +#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME "VK_NV_framebuffer_mixed_samples" + + +typedef enum VkCoverageModulationModeNV { + VK_COVERAGE_MODULATION_MODE_NONE_NV = 0, + VK_COVERAGE_MODULATION_MODE_RGB_NV = 1, + VK_COVERAGE_MODULATION_MODE_ALPHA_NV = 2, + VK_COVERAGE_MODULATION_MODE_RGBA_NV = 3, + VK_COVERAGE_MODULATION_MODE_BEGIN_RANGE_NV = VK_COVERAGE_MODULATION_MODE_NONE_NV, + VK_COVERAGE_MODULATION_MODE_END_RANGE_NV = VK_COVERAGE_MODULATION_MODE_RGBA_NV, + VK_COVERAGE_MODULATION_MODE_RANGE_SIZE_NV = (VK_COVERAGE_MODULATION_MODE_RGBA_NV - VK_COVERAGE_MODULATION_MODE_NONE_NV + 1), + VK_COVERAGE_MODULATION_MODE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoverageModulationModeNV; + +typedef VkFlags VkPipelineCoverageModulationStateCreateFlagsNV; + +typedef struct VkPipelineCoverageModulationStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCoverageModulationStateCreateFlagsNV flags; + VkCoverageModulationModeNV coverageModulationMode; + VkBool32 coverageModulationTableEnable; + uint32_t coverageModulationTableCount; + const float* pCoverageModulationTable; +} VkPipelineCoverageModulationStateCreateInfoNV; + + + +#define VK_NV_fill_rectangle 1 +#define VK_NV_FILL_RECTANGLE_SPEC_VERSION 1 +#define VK_NV_FILL_RECTANGLE_EXTENSION_NAME "VK_NV_fill_rectangle" + + +#define VK_EXT_post_depth_coverage 1 +#define VK_EXT_POST_DEPTH_COVERAGE_SPEC_VERSION 1 +#define VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME "VK_EXT_post_depth_coverage" + + +#define VK_EXT_validation_cache 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkValidationCacheEXT) + +#define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1 +#define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache" +#define VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT + + +typedef enum VkValidationCacheHeaderVersionEXT { + VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1, + VK_VALIDATION_CACHE_HEADER_VERSION_BEGIN_RANGE_EXT = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT, + VK_VALIDATION_CACHE_HEADER_VERSION_END_RANGE_EXT = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT, + VK_VALIDATION_CACHE_HEADER_VERSION_RANGE_SIZE_EXT = (VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT - VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT + 1), + VK_VALIDATION_CACHE_HEADER_VERSION_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationCacheHeaderVersionEXT; + +typedef VkFlags VkValidationCacheCreateFlagsEXT; + +typedef struct VkValidationCacheCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkValidationCacheCreateFlagsEXT flags; + size_t initialDataSize; + const void* pInitialData; +} VkValidationCacheCreateInfoEXT; + +typedef struct VkShaderModuleValidationCacheCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkValidationCacheEXT validationCache; +} VkShaderModuleValidationCacheCreateInfoEXT; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateValidationCacheEXT)(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache); +typedef void (VKAPI_PTR *PFN_vkDestroyValidationCacheEXT)(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkMergeValidationCachesEXT)(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches); +typedef VkResult (VKAPI_PTR *PFN_vkGetValidationCacheDataEXT)(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateValidationCacheEXT( + VkDevice device, + const VkValidationCacheCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkValidationCacheEXT* pValidationCache); + +VKAPI_ATTR void VKAPI_CALL vkDestroyValidationCacheEXT( + VkDevice device, + VkValidationCacheEXT validationCache, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkMergeValidationCachesEXT( + VkDevice device, + VkValidationCacheEXT dstCache, + uint32_t srcCacheCount, + const VkValidationCacheEXT* pSrcCaches); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetValidationCacheDataEXT( + VkDevice device, + VkValidationCacheEXT validationCache, + size_t* pDataSize, + void* pData); +#endif + +#define VK_EXT_shader_viewport_index_layer 1 +#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1 +#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer" + + +#define VK_EXT_global_priority 1 +#define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2 +#define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority" + + +typedef enum VkQueueGlobalPriorityEXT { + VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT = 128, + VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT = 256, + VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT = 512, + VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT = 1024, + VK_QUEUE_GLOBAL_PRIORITY_BEGIN_RANGE_EXT = VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT, + VK_QUEUE_GLOBAL_PRIORITY_END_RANGE_EXT = VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT, + VK_QUEUE_GLOBAL_PRIORITY_RANGE_SIZE_EXT = (VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT - VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT + 1), + VK_QUEUE_GLOBAL_PRIORITY_MAX_ENUM_EXT = 0x7FFFFFFF +} VkQueueGlobalPriorityEXT; + +typedef struct VkDeviceQueueGlobalPriorityCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkQueueGlobalPriorityEXT globalPriority; +} VkDeviceQueueGlobalPriorityCreateInfoEXT; + + + +#define VK_EXT_external_memory_host 1 +#define VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION 1 +#define VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME "VK_EXT_external_memory_host" + +typedef struct VkImportMemoryHostPointerInfoEXT { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + void* pHostPointer; +} VkImportMemoryHostPointerInfoEXT; + +typedef struct VkMemoryHostPointerPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryHostPointerPropertiesEXT; + +typedef struct VkPhysicalDeviceExternalMemoryHostPropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize minImportedHostPointerAlignment; +} VkPhysicalDeviceExternalMemoryHostPropertiesEXT; + + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryHostPointerPropertiesEXT)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + const void* pHostPointer, + VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); +#endif + +#define VK_AMD_buffer_marker 1 +#define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1 +#define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker" + +typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarkerAMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarkerAMD( + VkCommandBuffer commandBuffer, + VkPipelineStageFlagBits pipelineStage, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + uint32_t marker); +#endif + +#define VK_EXT_vertex_attribute_divisor 1 +#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 1 +#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor" + +typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxVertexAttribDivisor; +} VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT; + +typedef struct VkVertexInputBindingDivisorDescriptionEXT { + uint32_t binding; + uint32_t divisor; +} VkVertexInputBindingDivisorDescriptionEXT; + +typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t vertexBindingDivisorCount; + const VkVertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors; +} VkPipelineVertexInputDivisorStateCreateInfoEXT; + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/vulkan/vulkan_ios.h b/ext/vulkan/vulkan_ios.h new file mode 100644 index 0000000000..a0924816d5 --- /dev/null +++ b/ext/vulkan/vulkan_ios.h @@ -0,0 +1,58 @@ +#ifndef VULKAN_IOS_H_ +#define VULKAN_IOS_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2015-2018 The Khronos Group Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#define VK_MVK_ios_surface 1 +#define VK_MVK_IOS_SURFACE_SPEC_VERSION 2 +#define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface" + +typedef VkFlags VkIOSSurfaceCreateFlagsMVK; + +typedef struct VkIOSSurfaceCreateInfoMVK { + VkStructureType sType; + const void* pNext; + VkIOSSurfaceCreateFlagsMVK flags; + const void* pView; +} VkIOSSurfaceCreateInfoMVK; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateIOSSurfaceMVK)(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK( + VkInstance instance, + const VkIOSSurfaceCreateInfoMVK* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/vulkan/vulkan_macos.h b/ext/vulkan/vulkan_macos.h new file mode 100644 index 0000000000..ff0b701801 --- /dev/null +++ b/ext/vulkan/vulkan_macos.h @@ -0,0 +1,58 @@ +#ifndef VULKAN_MACOS_H_ +#define VULKAN_MACOS_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2015-2018 The Khronos Group Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#define VK_MVK_macos_surface 1 +#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 2 +#define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface" + +typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; + +typedef struct VkMacOSSurfaceCreateInfoMVK { + VkStructureType sType; + const void* pNext; + VkMacOSSurfaceCreateFlagsMVK flags; + const void* pView; +} VkMacOSSurfaceCreateInfoMVK; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateMacOSSurfaceMVK)(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK( + VkInstance instance, + const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/vulkan/vulkan_mir.h b/ext/vulkan/vulkan_mir.h new file mode 100644 index 0000000000..7d24ed27a3 --- /dev/null +++ b/ext/vulkan/vulkan_mir.h @@ -0,0 +1,65 @@ +#ifndef VULKAN_MIR_H_ +#define VULKAN_MIR_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2015-2018 The Khronos Group Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#define VK_KHR_mir_surface 1 +#define VK_KHR_MIR_SURFACE_SPEC_VERSION 4 +#define VK_KHR_MIR_SURFACE_EXTENSION_NAME "VK_KHR_mir_surface" + +typedef VkFlags VkMirSurfaceCreateFlagsKHR; + +typedef struct VkMirSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkMirSurfaceCreateFlagsKHR flags; + MirConnection* connection; + MirSurface* mirSurface; +} VkMirSurfaceCreateInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateMirSurfaceKHR)(VkInstance instance, const VkMirSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, MirConnection* connection); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR( + VkInstance instance, + const VkMirSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentationSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + MirConnection* connection); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/vulkan/vulkan_vi.h b/ext/vulkan/vulkan_vi.h new file mode 100644 index 0000000000..015166bfc6 --- /dev/null +++ b/ext/vulkan/vulkan_vi.h @@ -0,0 +1,58 @@ +#ifndef VULKAN_VI_H_ +#define VULKAN_VI_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2015-2018 The Khronos Group Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#define VK_NN_vi_surface 1 +#define VK_NN_VI_SURFACE_SPEC_VERSION 1 +#define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface" + +typedef VkFlags VkViSurfaceCreateFlagsNN; + +typedef struct VkViSurfaceCreateInfoNN { + VkStructureType sType; + const void* pNext; + VkViSurfaceCreateFlagsNN flags; + void* window; +} VkViSurfaceCreateInfoNN; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateViSurfaceNN)(VkInstance instance, const VkViSurfaceCreateInfoNN* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateViSurfaceNN( + VkInstance instance, + const VkViSurfaceCreateInfoNN* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/vulkan/vulkan_wayland.h b/ext/vulkan/vulkan_wayland.h new file mode 100644 index 0000000000..5ba0827aa3 --- /dev/null +++ b/ext/vulkan/vulkan_wayland.h @@ -0,0 +1,65 @@ +#ifndef VULKAN_WAYLAND_H_ +#define VULKAN_WAYLAND_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2015-2018 The Khronos Group Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#define VK_KHR_wayland_surface 1 +#define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6 +#define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface" + +typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; + +typedef struct VkWaylandSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkWaylandSurfaceCreateFlagsKHR flags; + struct wl_display* display; + struct wl_surface* surface; +} VkWaylandSurfaceCreateInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateWaylandSurfaceKHR)(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct wl_display* display); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR( + VkInstance instance, + const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + struct wl_display* display); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/vulkan/vulkan_win32.h b/ext/vulkan/vulkan_win32.h new file mode 100644 index 0000000000..6a85409ebe --- /dev/null +++ b/ext/vulkan/vulkan_win32.h @@ -0,0 +1,276 @@ +#ifndef VULKAN_WIN32_H_ +#define VULKAN_WIN32_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2015-2018 The Khronos Group Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#define VK_KHR_win32_surface 1 +#define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6 +#define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface" + +typedef VkFlags VkWin32SurfaceCreateFlagsKHR; + +typedef struct VkWin32SurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkWin32SurfaceCreateFlagsKHR flags; + HINSTANCE hinstance; + HWND hwnd; +} VkWin32SurfaceCreateInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateWin32SurfaceKHR)(VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR( + VkInstance instance, + const VkWin32SurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex); +#endif + +#define VK_KHR_external_memory_win32 1 +#define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32" + +typedef struct VkImportMemoryWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + HANDLE handle; + LPCWSTR name; +} VkImportMemoryWin32HandleInfoKHR; + +typedef struct VkExportMemoryWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + const SECURITY_ATTRIBUTES* pAttributes; + DWORD dwAccess; + LPCWSTR name; +} VkExportMemoryWin32HandleInfoKHR; + +typedef struct VkMemoryWin32HandlePropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryWin32HandlePropertiesKHR; + +typedef struct VkMemoryGetWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetWin32HandleInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHR( + VkDevice device, + const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, + HANDLE* pHandle); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + HANDLE handle, + VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties); +#endif + +#define VK_KHR_win32_keyed_mutex 1 +#define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1 +#define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex" + +typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t acquireCount; + const VkDeviceMemory* pAcquireSyncs; + const uint64_t* pAcquireKeys; + const uint32_t* pAcquireTimeouts; + uint32_t releaseCount; + const VkDeviceMemory* pReleaseSyncs; + const uint64_t* pReleaseKeys; +} VkWin32KeyedMutexAcquireReleaseInfoKHR; + + + +#define VK_KHR_external_semaphore_win32 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32" + +typedef struct VkImportSemaphoreWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkSemaphoreImportFlags flags; + VkExternalSemaphoreHandleTypeFlagBits handleType; + HANDLE handle; + LPCWSTR name; +} VkImportSemaphoreWin32HandleInfoKHR; + +typedef struct VkExportSemaphoreWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + const SECURITY_ATTRIBUTES* pAttributes; + DWORD dwAccess; + LPCWSTR name; +} VkExportSemaphoreWin32HandleInfoKHR; + +typedef struct VkD3D12FenceSubmitInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreValuesCount; + const uint64_t* pWaitSemaphoreValues; + uint32_t signalSemaphoreValuesCount; + const uint64_t* pSignalSemaphoreValues; +} VkD3D12FenceSubmitInfoKHR; + +typedef struct VkSemaphoreGetWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkSemaphoreGetWin32HandleInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHR)(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHR)(VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreWin32HandleKHR( + VkDevice device, + const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR( + VkDevice device, + const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, + HANDLE* pHandle); +#endif + +#define VK_KHR_external_fence_win32 1 +#define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32" + +typedef struct VkImportFenceWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkFenceImportFlags flags; + VkExternalFenceHandleTypeFlagBits handleType; + HANDLE handle; + LPCWSTR name; +} VkImportFenceWin32HandleInfoKHR; + +typedef struct VkExportFenceWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + const SECURITY_ATTRIBUTES* pAttributes; + DWORD dwAccess; + LPCWSTR name; +} VkExportFenceWin32HandleInfoKHR; + +typedef struct VkFenceGetWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkExternalFenceHandleTypeFlagBits handleType; +} VkFenceGetWin32HandleInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkImportFenceWin32HandleKHR)(VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetFenceWin32HandleKHR)(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceWin32HandleKHR( + VkDevice device, + const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR( + VkDevice device, + const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, + HANDLE* pHandle); +#endif + +#define VK_NV_external_memory_win32 1 +#define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32" + +typedef struct VkImportMemoryWin32HandleInfoNV { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagsNV handleType; + HANDLE handle; +} VkImportMemoryWin32HandleInfoNV; + +typedef struct VkExportMemoryWin32HandleInfoNV { + VkStructureType sType; + const void* pNext; + const SECURITY_ATTRIBUTES* pAttributes; + DWORD dwAccess; +} VkExportMemoryWin32HandleInfoNV; + + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleNV)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV( + VkDevice device, + VkDeviceMemory memory, + VkExternalMemoryHandleTypeFlagsNV handleType, + HANDLE* pHandle); +#endif + +#define VK_NV_win32_keyed_mutex 1 +#define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 1 +#define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex" + +typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t acquireCount; + const VkDeviceMemory* pAcquireSyncs; + const uint64_t* pAcquireKeys; + const uint32_t* pAcquireTimeoutMilliseconds; + uint32_t releaseCount; + const VkDeviceMemory* pReleaseSyncs; + const uint64_t* pReleaseKeys; +} VkWin32KeyedMutexAcquireReleaseInfoNV; + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/vulkan/vulkan_xcb.h b/ext/vulkan/vulkan_xcb.h new file mode 100644 index 0000000000..ba03600602 --- /dev/null +++ b/ext/vulkan/vulkan_xcb.h @@ -0,0 +1,66 @@ +#ifndef VULKAN_XCB_H_ +#define VULKAN_XCB_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2015-2018 The Khronos Group Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#define VK_KHR_xcb_surface 1 +#define VK_KHR_XCB_SURFACE_SPEC_VERSION 6 +#define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface" + +typedef VkFlags VkXcbSurfaceCreateFlagsKHR; + +typedef struct VkXcbSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkXcbSurfaceCreateFlagsKHR flags; + xcb_connection_t* connection; + xcb_window_t window; +} VkXcbSurfaceCreateInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateXcbSurfaceKHR)(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR( + VkInstance instance, + const VkXcbSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + xcb_connection_t* connection, + xcb_visualid_t visual_id); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/vulkan/vulkan_xlib.h b/ext/vulkan/vulkan_xlib.h new file mode 100644 index 0000000000..e1d967e018 --- /dev/null +++ b/ext/vulkan/vulkan_xlib.h @@ -0,0 +1,66 @@ +#ifndef VULKAN_XLIB_H_ +#define VULKAN_XLIB_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2015-2018 The Khronos Group Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#define VK_KHR_xlib_surface 1 +#define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6 +#define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface" + +typedef VkFlags VkXlibSurfaceCreateFlagsKHR; + +typedef struct VkXlibSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkXlibSurfaceCreateFlagsKHR flags; + Display* dpy; + Window window; +} VkXlibSurfaceCreateInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateXlibSurfaceKHR)(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR( + VkInstance instance, + const VkXlibSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + Display* dpy, + VisualID visualID); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/vulkan/vulkan_xlib_xrandr.h b/ext/vulkan/vulkan_xlib_xrandr.h new file mode 100644 index 0000000000..117d01799e --- /dev/null +++ b/ext/vulkan/vulkan_xlib_xrandr.h @@ -0,0 +1,54 @@ +#ifndef VULKAN_XLIB_XRANDR_H_ +#define VULKAN_XLIB_XRANDR_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2015-2018 The Khronos Group Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#define VK_EXT_acquire_xlib_display 1 +#define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1 +#define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display" + +typedef VkResult (VKAPI_PTR *PFN_vkAcquireXlibDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetRandROutputDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, RROutput rrOutput, VkDisplayKHR* pDisplay); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireXlibDisplayEXT( + VkPhysicalDevice physicalDevice, + Display* dpy, + VkDisplayKHR display); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRandROutputDisplayEXT( + VkPhysicalDevice physicalDevice, + Display* dpy, + RROutput rrOutput, + VkDisplayKHR* pDisplay); +#endif + +#ifdef __cplusplus +} +#endif + +#endif From 1bb7be489f8773784e4c1554555e88b6f67d7bca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Mar 2018 10:33:50 +0100 Subject: [PATCH 261/291] Remove some unused tracking of whether lighting is used by a shader --- GPU/D3D11/ShaderManagerD3D11.cpp | 9 ++++----- GPU/D3D11/ShaderManagerD3D11.h | 6 +----- GPU/D3D11/VertexShaderGeneratorD3D11.cpp | 3 +-- GPU/D3D11/VertexShaderGeneratorD3D11.h | 2 +- GPU/Vulkan/PipelineManagerVulkan.cpp | 7 +------ GPU/Vulkan/PipelineManagerVulkan.h | 2 -- GPU/Vulkan/ShaderManagerVulkan.cpp | 14 ++++++-------- GPU/Vulkan/ShaderManagerVulkan.h | 6 +----- GPU/Vulkan/VertexShaderGeneratorVulkan.cpp | 6 +----- GPU/Vulkan/VertexShaderGeneratorVulkan.h | 2 +- 10 files changed, 17 insertions(+), 40 deletions(-) diff --git a/GPU/D3D11/ShaderManagerD3D11.cpp b/GPU/D3D11/ShaderManagerD3D11.cpp index 3efb79ace3..7e79d57224 100644 --- a/GPU/D3D11/ShaderManagerD3D11.cpp +++ b/GPU/D3D11/ShaderManagerD3D11.cpp @@ -63,8 +63,8 @@ std::string D3D11FragmentShader::GetShaderString(DebugShaderStringType type) con } } -D3D11VertexShader::D3D11VertexShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, VShaderID id, const char *code, int vertType, bool useHWTransform, bool usesLighting) - : device_(device), id_(id), failed_(false), useHWTransform_(useHWTransform), module_(nullptr), usesLighting_(usesLighting) { +D3D11VertexShader::D3D11VertexShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, VShaderID id, const char *code, int vertType, bool useHWTransform) + : device_(device), id_(id), failed_(false), useHWTransform_(useHWTransform), module_(nullptr) { source_ = code; module_ = CreateVertexShaderD3D11(device, code, strlen(code), &bytecode_, featureLevel); @@ -196,9 +196,8 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader ** D3D11VertexShader *vs; if (vsIter == vsCache_.end()) { // Vertex shader not in cache. Let's compile it. - bool usesLighting; - GenerateVertexShaderD3D11(VSID, codeBuffer_, &usesLighting, featureLevel_ <= D3D_FEATURE_LEVEL_9_3 ? HLSL_D3D11_LEVEL9 : HLSL_D3D11); - vs = new D3D11VertexShader(device_, featureLevel_, VSID, codeBuffer_, vertType, useHWTransform, usesLighting); + GenerateVertexShaderD3D11(VSID, codeBuffer_, featureLevel_ <= D3D_FEATURE_LEVEL_9_3 ? HLSL_D3D11_LEVEL9 : HLSL_D3D11); + vs = new D3D11VertexShader(device_, featureLevel_, VSID, codeBuffer_, vertType, useHWTransform); vsCache_[VSID] = vs; } else { vs = vsIter->second; diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index 3b4a21b961..cc0da972bd 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -54,16 +54,13 @@ protected: class D3D11VertexShader { public: - D3D11VertexShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, VShaderID id, const char *code, int vertType, bool useHWTransform, bool usesLighting); + D3D11VertexShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, VShaderID id, const char *code, int vertType, bool useHWTransform); ~D3D11VertexShader(); const std::string &source() const { return source_; } const std::vector &bytecode() const { return bytecode_; } bool Failed() const { return failed_; } bool UseHWTransform() const { return useHWTransform_; } - bool HasLights() const { - return usesLighting_; - } std::string GetShaderString(DebugShaderStringType type) const; ID3D11VertexShader *GetShader() const { return module_; } @@ -77,7 +74,6 @@ protected: bool failed_; bool useHWTransform_; - bool usesLighting_; VShaderID id_; }; diff --git a/GPU/D3D11/VertexShaderGeneratorD3D11.cpp b/GPU/D3D11/VertexShaderGeneratorD3D11.cpp index 1153d6358c..75affc997d 100644 --- a/GPU/D3D11/VertexShaderGeneratorD3D11.cpp +++ b/GPU/D3D11/VertexShaderGeneratorD3D11.cpp @@ -19,7 +19,6 @@ #include "GPU/D3D11/VertexShaderGeneratorD3D11.h" #include "GPU/Directx9/VertexShaderGeneratorDX9.h" -void GenerateVertexShaderD3D11(const VShaderID &id, char *buffer, bool *usesLighting, ShaderLanguage lang) { - *usesLighting = true; +void GenerateVertexShaderD3D11(const VShaderID &id, char *buffer, ShaderLanguage lang) { DX9::GenerateVertexShaderHLSL(id, buffer, lang); } diff --git a/GPU/D3D11/VertexShaderGeneratorD3D11.h b/GPU/D3D11/VertexShaderGeneratorD3D11.h index e9c6d0ca42..fcf6f7f749 100644 --- a/GPU/D3D11/VertexShaderGeneratorD3D11.h +++ b/GPU/D3D11/VertexShaderGeneratorD3D11.h @@ -19,4 +19,4 @@ #include "GPU/Common/ShaderId.h" -void GenerateVertexShaderD3D11(const VShaderID &id, char *buffer, bool *usesLighting, ShaderLanguage lang); +void GenerateVertexShaderD3D11(const VShaderID &id, char *buffer, ShaderLanguage lang); diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index cfea933c15..9fd4ba254f 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -281,16 +281,11 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip VulkanPipeline *vulkanPipeline = new VulkanPipeline(); vulkanPipeline->pipeline = pipeline; - vulkanPipeline->flags = PIPELINE_FLAG_USES_BASE_UB; + vulkanPipeline->flags = 0; if (useBlendConstant) vulkanPipeline->flags |= PIPELINE_FLAG_USES_BLEND_CONSTANT; if (key.topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST || key.topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP) vulkanPipeline->flags |= PIPELINE_FLAG_USES_LINES; - if (useHwTransform) { - if (vs->HasLights()) { - vulkanPipeline->flags |= PIPELINE_FLAG_USES_LIGHT_UB; - } - } return vulkanPipeline; } diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index 4494fbc41d..6cf98c7ed4 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -63,8 +63,6 @@ struct StoredVulkanPipelineKey { }; enum PipelineFlags { - PIPELINE_FLAG_USES_BASE_UB = (1 << 0), - PIPELINE_FLAG_USES_LIGHT_UB = (1 << 1), PIPELINE_FLAG_USES_LINES = (1 << 2), PIPELINE_FLAG_USES_BLEND_CONSTANT = (1 << 3), }; diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 9b525ec29b..b753ebd19a 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -98,8 +98,8 @@ std::string VulkanFragmentShader::GetShaderString(DebugShaderStringType type) co } } -VulkanVertexShader::VulkanVertexShader(VulkanContext *vulkan, VShaderID id, const char *code, bool useHWTransform, bool usesLighting) - : vulkan_(vulkan), id_(id), failed_(false), useHWTransform_(useHWTransform), module_(VK_NULL_HANDLE), usesLighting_(usesLighting) { +VulkanVertexShader::VulkanVertexShader(VulkanContext *vulkan, VShaderID id, const char *code, bool useHWTransform) + : vulkan_(vulkan), id_(id), failed_(false), useHWTransform_(useHWTransform), module_(VK_NULL_HANDLE) { PROFILE_THIS_SCOPE("shadercomp"); source_ = code; std::string errorMessage; @@ -252,9 +252,8 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader VulkanVertexShader *vs = vsCache_.Get(VSID); if (!vs) { // Vertex shader not in cache. Let's compile it. - bool usesLighting; - GenerateVulkanGLSLVertexShader(VSID, codeBuffer_, &usesLighting); - vs = new VulkanVertexShader(vulkan_, VSID, codeBuffer_, useHWTransform, usesLighting); + GenerateVulkanGLSLVertexShader(VSID, codeBuffer_); + vs = new VulkanVertexShader(vulkan_, VSID, codeBuffer_, useHWTransform); vsCache_.Insert(VSID, vs); } lastVSID_ = VSID; @@ -375,9 +374,8 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) { VShaderID id; fread(&id, sizeof(id), 1, f); bool useHWTransform = id.Bit(VS_BIT_USE_HW_TRANSFORM); - bool usesLighting; - GenerateVulkanGLSLVertexShader(id, codeBuffer_, &usesLighting); - VulkanVertexShader *vs = new VulkanVertexShader(vulkan_, id, codeBuffer_, useHWTransform, usesLighting); + GenerateVulkanGLSLVertexShader(id, codeBuffer_); + VulkanVertexShader *vs = new VulkanVertexShader(vulkan_, id, codeBuffer_, useHWTransform); vsCache_.Insert(id, vs); } for (int i = 0; i < header.numFragmentShaders; i++) { diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index 8e6db9495c..281d4768e0 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -57,16 +57,13 @@ protected: class VulkanVertexShader { public: - VulkanVertexShader(VulkanContext *vulkan, VShaderID id, const char *code, bool useHWTransform, bool usesLighting); + VulkanVertexShader(VulkanContext *vulkan, VShaderID id, const char *code, bool useHWTransform); ~VulkanVertexShader(); const std::string &source() const { return source_; } bool Failed() const { return failed_; } bool UseHWTransform() const { return useHWTransform_; } - bool HasLights() const { - return usesLighting_; - } std::string GetShaderString(DebugShaderStringType type) const; VkShaderModule GetModule() const { return module_; } @@ -79,7 +76,6 @@ protected: std::string source_; bool failed_; bool useHWTransform_; - bool usesLighting_; VShaderID id_; }; diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp index 4627118ab5..eaeb8b9180 100644 --- a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp @@ -85,7 +85,7 @@ enum DoLightComputation { // TODO: Skip all this if we can actually get a 16-bit depth buffer along with stencil, which // is a bit of a rare configuration, although quite common on mobile. -bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *usesLighting) { +bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer) { char *p = buffer; WRITE(p, "%s", vulkan_glsl_preamble); @@ -123,10 +123,6 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *use bool hasTexcoordTess = id.Bit(VS_BIT_HAS_TEXCOORD_TESS); bool flipNormalTess = id.Bit(VS_BIT_NORM_REVERSE_TESS); - // The uniforms are passed in as three "clumps" that may or may not be present. - // We will memcpy the parts into place in a big buffer so we can be quite dynamic about what parts - // are present and what parts aren't, but we will not be ultra detailed about it. - *usesLighting = enableLighting || doShadeMapping; WRITE(p, "\n"); WRITE(p, "layout (std140, set = 0, binding = 2) uniform baseVars {\n%s} base;\n", ub_baseStr); if (enableLighting || doShadeMapping) diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.h b/GPU/Vulkan/VertexShaderGeneratorVulkan.h index e1c75a7a46..1501c1cdae 100644 --- a/GPU/Vulkan/VertexShaderGeneratorVulkan.h +++ b/GPU/Vulkan/VertexShaderGeneratorVulkan.h @@ -2,4 +2,4 @@ #include "GPU/Common/ShaderId.h" -bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *usesLighting); +bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer); From 08c3e13517505fce8d4e359f3ca98337e75a3c4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Mar 2018 11:03:24 +0100 Subject: [PATCH 262/291] Do more detailed checks for Vulkan availability. Should hopefully solve #10729. --- Common/Vulkan/VulkanContext.cpp | 1 + Common/Vulkan/VulkanLoader.cpp | 119 +++++++++++++++++++++++++-- Common/Vulkan/VulkanLoader.h | 1 + android/jni/AndroidVulkanContext.cpp | 4 +- android/jni/app-android.cpp | 2 +- 5 files changed, 117 insertions(+), 10 deletions(-) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index c14d6a561e..77fa7ed392 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -579,6 +579,7 @@ VkResult VulkanContext::CreateDevice() { VulkanLoadDeviceFunctions(device_); } ILOG("Device created.\n"); + VulkanSetAvailable(true); return res; } diff --git a/Common/Vulkan/VulkanLoader.cpp b/Common/Vulkan/VulkanLoader.cpp index 907f2d61e8..01f1d1c178 100644 --- a/Common/Vulkan/VulkanLoader.cpp +++ b/Common/Vulkan/VulkanLoader.cpp @@ -16,6 +16,7 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "Common/Vulkan/VulkanLoader.h" +#include #include "base/logging.h" #include "base/basictypes.h" @@ -203,37 +204,139 @@ static HINSTANCE vulkanLibrary; static void *vulkanLibrary; #endif +bool g_vulkanAvailabilityChecked = false; +bool g_vulkanMayBeAvailable = false; + #define LOAD_INSTANCE_FUNC(instance, x) x = (PFN_ ## x)vkGetInstanceProcAddr(instance, #x); if (!x) {ILOG("Missing (instance): %s", #x);} #define LOAD_DEVICE_FUNC(instance, x) x = (PFN_ ## x)vkGetDeviceProcAddr(instance, #x); if (!x) {ILOG("Missing (device): %s", #x);} #define LOAD_GLOBAL_FUNC(x) x = (PFN_ ## x)dlsym(vulkanLibrary, #x); if (!x) {ILOG("Missing (global): %s", #x);} +#define LOAD_GLOBAL_FUNC_LOCAL(lib, x) (PFN_ ## x)dlsym(lib, #x); + static const char *so_names[] = { "libvulkan.so", "libvulkan.so.1", }; +void VulkanSetAvailable(bool available) { + g_vulkanAvailabilityChecked = true; + g_vulkanMayBeAvailable = available; +} + bool VulkanMayBeAvailable() { - if (vulkanLibrary) - return true; + if (g_vulkanAvailabilityChecked) + return g_vulkanMayBeAvailable; bool available = false; #ifndef _WIN32 + void *lib = nullptr; for (int i = 0; i < ARRAY_SIZE(so_names); i++) { - void *lib = dlopen(so_names[i], RTLD_NOW | RTLD_LOCAL); + lib = dlopen(so_names[i], RTLD_NOW | RTLD_LOCAL); if (lib) { available = true; - dlclose(lib); break; } } #else // LoadLibrary etc HINSTANCE lib = LoadLibrary(L"vulkan-1.dll"); + available = lib != 0; - if (lib) { - FreeLibrary(lib); - } #endif - return available; + // Do a hyper minimal initialization and teardown to figure out if there's any chance + // that any sort of Vulkan will be usable. + PFN_vkCreateInstance localCreateInstance = LOAD_GLOBAL_FUNC_LOCAL(lib, vkCreateInstance); + PFN_vkEnumeratePhysicalDevices localEnumerate = LOAD_GLOBAL_FUNC_LOCAL(lib, vkEnumeratePhysicalDevices); + PFN_vkDestroyInstance localDestroyInstance = LOAD_GLOBAL_FUNC_LOCAL(lib, vkDestroyInstance); + PFN_vkGetPhysicalDeviceProperties localGetPhysicalDeviceProperties = LOAD_GLOBAL_FUNC_LOCAL(lib, vkGetPhysicalDeviceProperties); + + // Need to predeclare all this because of the gotos... + VkInstanceCreateInfo ci{ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; + VkApplicationInfo info{ VK_STRUCTURE_TYPE_APPLICATION_INFO }; + std::vector devices; + bool anyGood; + const char *instanceExtensions[1]; + int extCount = 0; + VkInstance instance = VK_NULL_HANDLE; + VkResult res; + uint32_t physicalDeviceCount = 0; + + if (!localCreateInstance || !localEnumerate || !localDestroyInstance || !localGetPhysicalDeviceProperties) + goto bail; + +#ifdef _WIN32 + instanceExtensions[0] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME; + ci.enabledExtensionCount = 1; +#elif defined(__ANDROID__) + instanceExtensions[0] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME; + ci.enabledExtensionCount = 1; +#endif + ci.ppEnabledExtensionNames = instanceExtensions; + ci.enabledLayerCount = 0; + info.apiVersion = VK_API_VERSION_1_0; + info.applicationVersion = 1; + info.engineVersion = 1; + info.pApplicationName = "VulkanChecker"; + info.pEngineName = "VulkanChecker"; + ci.pApplicationInfo = &info; + ci.flags = 0; + res = localCreateInstance(&ci, nullptr, &instance); + if (res != VK_SUCCESS) { + ELOG("Failed to create vulkan instance."); + goto bail; + } + ILOG("Vulkan test instance created successfully."); + res = localEnumerate(instance, &physicalDeviceCount, nullptr); + if (res != VK_SUCCESS) { + ELOG("Failed to count physical devices."); + goto bail; + } + if (physicalDeviceCount == 0) { + ELOG("No physical Vulkan devices."); + goto bail; + } + devices.resize(physicalDeviceCount); + res = localEnumerate(instance, &physicalDeviceCount, devices.data()); + if (res != VK_SUCCESS) { + ELOG("Failed to enumerate physical devices."); + goto bail; + } + anyGood = false; + for (auto device : devices) { + VkPhysicalDeviceProperties props; + localGetPhysicalDeviceProperties(device, &props); + switch (props.deviceType) { + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: + case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: + anyGood = true; + break; + } + // TODO: Should also check queuefamilyproperties for a GRAPHICS queue family? Oh well. + } + + if (!anyGood) { + WLOG("Found Vulkan API, but no good Vulkan device!"); + g_vulkanMayBeAvailable = false; + } else { + ILOG("Found working Vulkan API!"); + g_vulkanMayBeAvailable = true; + } + +bail: + g_vulkanAvailabilityChecked = true; + if (instance) { + localDestroyInstance(instance, nullptr); + } + if (lib) { +#ifndef _WIN32 + dlclose(lib); +#else + FreeLibrary(lib); +#endif + } else { + ELOG("Vulkan with working device not detected."); + } + return g_vulkanMayBeAvailable; } bool VulkanLoad() { diff --git a/Common/Vulkan/VulkanLoader.h b/Common/Vulkan/VulkanLoader.h index 636bff82c7..d51d833da5 100644 --- a/Common/Vulkan/VulkanLoader.h +++ b/Common/Vulkan/VulkanLoader.h @@ -201,6 +201,7 @@ extern PFN_vkDestroyDebugReportCallbackEXT dyn_vkDestroyDebugReportCallbackEXT; // Way to do a quick check before even attempting to load. bool VulkanMayBeAvailable(); +void VulkanSetAvailable(bool available); bool VulkanLoad(); void VulkanLoadInstanceFunctions(VkInstance instance); diff --git a/android/jni/AndroidVulkanContext.cpp b/android/jni/AndroidVulkanContext.cpp index d41c6af5ad..4240bde18c 100644 --- a/android/jni/AndroidVulkanContext.cpp +++ b/android/jni/AndroidVulkanContext.cpp @@ -98,9 +98,11 @@ bool AndroidVulkanContext::InitAPI() { info.app_name = "PPSSPP"; info.app_ver = gitVer.ToInteger(); info.flags = VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_FIFO_RELAXED; - if (VK_SUCCESS != g_Vulkan->CreateInstance(info)) { + VkResult res = g_Vulkan->CreateInstance(info); + if (res != VK_SUCCESS) { ELOG("Failed to create vulkan context: %s", g_Vulkan->InitError().c_str()); System_SendMessage("toast", "No Vulkan compatible device found. Using OpenGL instead."); + VulkanSetAvailable(false); delete g_Vulkan; g_Vulkan = nullptr; return false; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 49d472ceba..335230f3ef 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -431,10 +431,10 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init NativeInit(2, argv, user_data_path.c_str(), externalDir.c_str(), cacheDir.c_str()); } - retry: // Now that we've loaded config, set javaGL. javaGL = NativeQueryConfig("androidJavaGL") == "true"; + switch (g_Config.iGPUBackend) { case (int)GPUBackend::OPENGL: useCPUThread = true; From 99af1d58ad516149d9604e8464ebb1e7014604e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Mar 2018 13:45:12 +0100 Subject: [PATCH 263/291] OpenGL task switching fix --- GPU/GLES/FramebufferManagerGLES.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index eb027bf453..53cb7cd638 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -754,6 +754,7 @@ void FramebufferManagerGLES::DeviceLost() { void FramebufferManagerGLES::DeviceRestore(Draw::DrawContext *draw) { draw_ = draw; + render_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); CreateDeviceObjects(); } From 7ae4a9e9776321c3932d9e767b71060a52716267 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Mar 2018 07:42:07 -0700 Subject: [PATCH 264/291] Vulkan: Load shaders/pipelines on thread. In case it's slow when not reading raw cache data. --- GPU/Vulkan/GPU_Vulkan.cpp | 12 +++++++++++- GPU/Vulkan/GPU_Vulkan.h | 3 +++ GPU/Vulkan/PipelineManagerVulkan.cpp | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index c073f8d95b..30598c92e9 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -16,6 +16,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include #include "base/logging.h" #include "profiler/profiler.h" @@ -101,11 +102,20 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) if (discID.size()) { File::CreateFullPath(GetSysDirectory(DIRECTORY_APP_CACHE)); shaderCachePath_ = GetSysDirectory(DIRECTORY_APP_CACHE) + "/" + discID + ".vkshadercache"; + shaderCacheLoaded_ = false; - LoadCache(shaderCachePath_); + std::thread th([&] { + LoadCache(shaderCachePath_); + shaderCacheLoaded_ = true; + }); + th.detach(); } } +bool GPU_Vulkan::IsReady() { + return shaderCacheLoaded_; +} + void GPU_Vulkan::LoadCache(std::string filename) { PSP_SetLoading("Loading shader cache..."); // Actually precompiled by IsReady() since we're single-threaded. diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 7e81e6c271..d4ce2151a2 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -38,6 +38,8 @@ public: // This gets called on startup and when we get back from settings. void CheckGPUFeatures() override; + bool IsReady() override; + // These are where we can reset command buffers etc. void BeginHostFrame() override; void EndHostFrame() override; @@ -105,4 +107,5 @@ private: FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES]{}; std::string shaderCachePath_; + bool shaderCacheLoaded_ = false; }; diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 9fd4ba254f..6e9a62aeb9 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -602,12 +602,12 @@ bool PipelineManagerVulkan::LoadCache(FILE *file, bool loadRawPipelineCache, Sha } else { vkMergePipelineCaches(vulkan_->GetDevice(), pipelineCache_, 1, &cache); } + NOTICE_LOG(G3D, "Loaded Vulkan pipeline cache (%d bytes).", (int)size); } else { if (!pipelineCache_) { VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_); } - NOTICE_LOG(G3D, "Loaded Vulkan pipeline cache (%d bytes).", (int)size); } // Read the number of pipelines. From 473c87273fc3afacdfac5a48c9d31e4324fa09f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Mar 2018 19:22:59 +0100 Subject: [PATCH 265/291] Maybe slightly safer vulkan detection code. Might help #10732 --- Common/Vulkan/VulkanLoader.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Common/Vulkan/VulkanLoader.cpp b/Common/Vulkan/VulkanLoader.cpp index 01f1d1c178..0d41785a28 100644 --- a/Common/Vulkan/VulkanLoader.cpp +++ b/Common/Vulkan/VulkanLoader.cpp @@ -226,22 +226,24 @@ void VulkanSetAvailable(bool available) { bool VulkanMayBeAvailable() { if (g_vulkanAvailabilityChecked) return g_vulkanMayBeAvailable; - bool available = false; #ifndef _WIN32 void *lib = nullptr; for (int i = 0; i < ARRAY_SIZE(so_names); i++) { lib = dlopen(so_names[i], RTLD_NOW | RTLD_LOCAL); if (lib) { - available = true; break; } } #else // LoadLibrary etc HINSTANCE lib = LoadLibrary(L"vulkan-1.dll"); - - available = lib != 0; #endif + if (!lib) { + g_vulkanAvailabilityChecked = true; + g_vulkanMayBeAvailable = false; + return false; + } + // Do a hyper minimal initialization and teardown to figure out if there's any chance // that any sort of Vulkan will be usable. PFN_vkCreateInstance localCreateInstance = LOAD_GLOBAL_FUNC_LOCAL(lib, vkCreateInstance); @@ -253,9 +255,8 @@ bool VulkanMayBeAvailable() { VkInstanceCreateInfo ci{ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; VkApplicationInfo info{ VK_STRUCTURE_TYPE_APPLICATION_INFO }; std::vector devices; - bool anyGood; - const char *instanceExtensions[1]; - int extCount = 0; + bool anyGood = false; + const char *instanceExtensions[1]{}; VkInstance instance = VK_NULL_HANDLE; VkResult res; uint32_t physicalDeviceCount = 0; @@ -270,6 +271,7 @@ bool VulkanMayBeAvailable() { instanceExtensions[0] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME; ci.enabledExtensionCount = 1; #endif + ci.ppEnabledExtensionNames = instanceExtensions; ci.enabledLayerCount = 0; info.apiVersion = VK_API_VERSION_1_0; @@ -281,6 +283,7 @@ bool VulkanMayBeAvailable() { ci.flags = 0; res = localCreateInstance(&ci, nullptr, &instance); if (res != VK_SUCCESS) { + instance = nullptr; ELOG("Failed to create vulkan instance."); goto bail; } From f14f2efa793468a1d06675fcd1a61ddc61737d5a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Mar 2018 13:33:48 -0700 Subject: [PATCH 266/291] Module: Hash functions only once during loading. This fixes the loading speed regression from #10501. --- Core/HLE/sceKernelModule.cpp | 17 +++++++++++------ Core/MIPS/MIPSAnalyst.cpp | 9 +++++++-- Core/MIPS/MIPSAnalyst.h | 3 ++- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index ff9826ebe9..63c2d12927 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1268,7 +1268,7 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd scan = g_Config.bFuncReplacements; #endif - bool gotSymbols = scan && reader.LoadSymbols(); + bool insertSymbols = scan && !reader.LoadSymbols(); std::vector codeSections = reader.GetCodeSections(); for (SectionID id : codeSections) { u32 start = reader.GetSectionAddr(id); @@ -1280,8 +1280,9 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd if (end > module->textEnd) module->textEnd = end; - if (scan) - MIPSAnalyst::ScanForFunctions(start, end, !gotSymbols); + if (scan) { + MIPSAnalyst::ScanForFunctions(start, end, insertSymbols); + } } // Some games don't have any sections at all. @@ -1290,14 +1291,18 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd u32 scanEnd = module->textEnd; // Skip the exports and imports sections, they're not code. if (scanEnd >= std::min(modinfo->libent, modinfo->libstub)) { - MIPSAnalyst::ScanForFunctions(scanStart, std::min(modinfo->libent, modinfo->libstub) - 4, !gotSymbols); + MIPSAnalyst::ScanForFunctions(scanStart, std::min(modinfo->libent, modinfo->libstub) - 4, insertSymbols); scanStart = std::min(modinfo->libentend, modinfo->libstubend); } if (scanEnd >= std::max(modinfo->libent, modinfo->libstub)) { - MIPSAnalyst::ScanForFunctions(scanStart, std::max(modinfo->libent, modinfo->libstub) - 4, !gotSymbols); + MIPSAnalyst::ScanForFunctions(scanStart, std::max(modinfo->libent, modinfo->libstub) - 4, insertSymbols); scanStart = std::max(modinfo->libentend, modinfo->libstubend); } - MIPSAnalyst::ScanForFunctions(scanStart, scanEnd, !gotSymbols); + MIPSAnalyst::ScanForFunctions(scanStart, scanEnd, insertSymbols); + } + + if (scan) { + MIPSAnalyst::FinalizeScan(insertSymbols); } } diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index 98d07490ab..b72120ca06 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -878,13 +878,16 @@ namespace MIPSAnalyst { for (auto iter = functions.begin(), end = functions.end(); iter != end; iter++) { AnalyzedFunction &f = *iter; + if (Memory::IsValidRange(f.start, f.end - f.start + 4)) { + continue; + } // This is unfortunate. In case of emuhacks or relocs, we have to make a copy. buffer.resize((f.end - f.start + 4) / 4); size_t pos = 0; for (u32 addr = f.start; addr <= f.end; addr += 4) { u32 validbits = 0xFFFFFFFF; - MIPSOpcode instr = Memory::Read_Instruction(addr, true); + MIPSOpcode instr = Memory::ReadUnchecked_Instruction(addr, true); if (MIPS_IS_EMUHACK(instr)) { f.hasHash = false; goto skip; @@ -1015,7 +1018,7 @@ skip: return furthestJumpbackAddr; } - void ScanForFunctions(u32 startAddr, u32 endAddr, bool insertSymbols) { + void ScanForFunctions(u32 startAddr, u32 endAddr, bool &insertSymbols) { std::lock_guard guard(functions_lock); AnalyzedFunction currentFunction = {startAddr}; @@ -1163,7 +1166,9 @@ skip: g_symbolMap->AddFunction(DefaultFunctionName(temp, iter->start), iter->start, iter->end - iter->start + 4); } } + } + void FinalizeScan(bool insertSymbols) { HashFunctions(); std::string hashMapFilename = GetSysDirectory(DIRECTORY_SYSTEM) + "knownfuncs.ini"; diff --git a/Core/MIPS/MIPSAnalyst.h b/Core/MIPS/MIPSAnalyst.h index 9d6683c48a..030ff0e95c 100644 --- a/Core/MIPS/MIPSAnalyst.h +++ b/Core/MIPS/MIPSAnalyst.h @@ -105,7 +105,8 @@ namespace MIPSAnalyst // If we have loaded symbols from the elf, we'll register functions as they are touched // so that we don't just dump them all in the cache. void RegisterFunction(u32 startAddr, u32 size, const char *name); - void ScanForFunctions(u32 startAddr, u32 endAddr, bool insertSymbols); + void ScanForFunctions(u32 startAddr, u32 endAddr, bool &insertSymbols); + void FinalizeScan(bool insertSymbols); void ForgetFunctions(u32 startAddr, u32 endAddr); void PrecompileFunctions(); void PrecompileFunction(u32 startAddr, u32 length); From 892c439fcf11599f3f74e54f626d5e61361a3f4a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Mar 2018 13:58:56 -0700 Subject: [PATCH 267/291] Module: Clarify insertSymbols usage. --- Core/HLE/sceKernelModule.cpp | 9 +++++---- Core/MIPS/MIPSAnalyst.cpp | 4 +++- Core/MIPS/MIPSAnalyst.h | 3 ++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 63c2d12927..82da25de65 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1268,6 +1268,7 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd scan = g_Config.bFuncReplacements; #endif + // If the ELF has debug symbols, don't add entries to the symbol table. bool insertSymbols = scan && !reader.LoadSymbols(); std::vector codeSections = reader.GetCodeSections(); for (SectionID id : codeSections) { @@ -1281,7 +1282,7 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd module->textEnd = end; if (scan) { - MIPSAnalyst::ScanForFunctions(start, end, insertSymbols); + insertSymbols = MIPSAnalyst::ScanForFunctions(start, end, insertSymbols); } } @@ -1291,14 +1292,14 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd u32 scanEnd = module->textEnd; // Skip the exports and imports sections, they're not code. if (scanEnd >= std::min(modinfo->libent, modinfo->libstub)) { - MIPSAnalyst::ScanForFunctions(scanStart, std::min(modinfo->libent, modinfo->libstub) - 4, insertSymbols); + insertSymbols = MIPSAnalyst::ScanForFunctions(scanStart, std::min(modinfo->libent, modinfo->libstub) - 4, insertSymbols); scanStart = std::min(modinfo->libentend, modinfo->libstubend); } if (scanEnd >= std::max(modinfo->libent, modinfo->libstub)) { - MIPSAnalyst::ScanForFunctions(scanStart, std::max(modinfo->libent, modinfo->libstub) - 4, insertSymbols); + insertSymbols = MIPSAnalyst::ScanForFunctions(scanStart, std::max(modinfo->libent, modinfo->libstub) - 4, insertSymbols); scanStart = std::max(modinfo->libentend, modinfo->libstubend); } - MIPSAnalyst::ScanForFunctions(scanStart, scanEnd, insertSymbols); + insertSymbols = MIPSAnalyst::ScanForFunctions(scanStart, scanEnd, insertSymbols); } if (scan) { diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index b72120ca06..9a31123fef 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -1018,7 +1018,7 @@ skip: return furthestJumpbackAddr; } - void ScanForFunctions(u32 startAddr, u32 endAddr, bool &insertSymbols) { + bool ScanForFunctions(u32 startAddr, u32 endAddr, bool insertSymbols) { std::lock_guard guard(functions_lock); AnalyzedFunction currentFunction = {startAddr}; @@ -1166,6 +1166,8 @@ skip: g_symbolMap->AddFunction(DefaultFunctionName(temp, iter->start), iter->start, iter->end - iter->start + 4); } } + + return insertSymbols; } void FinalizeScan(bool insertSymbols) { diff --git a/Core/MIPS/MIPSAnalyst.h b/Core/MIPS/MIPSAnalyst.h index 030ff0e95c..746fa26f90 100644 --- a/Core/MIPS/MIPSAnalyst.h +++ b/Core/MIPS/MIPSAnalyst.h @@ -105,7 +105,8 @@ namespace MIPSAnalyst // If we have loaded symbols from the elf, we'll register functions as they are touched // so that we don't just dump them all in the cache. void RegisterFunction(u32 startAddr, u32 size, const char *name); - void ScanForFunctions(u32 startAddr, u32 endAddr, bool &insertSymbols); + // Returns new insertSymbols value for FinalizeScan(). + bool ScanForFunctions(u32 startAddr, u32 endAddr, bool insertSymbols); void FinalizeScan(bool insertSymbols); void ForgetFunctions(u32 startAddr, u32 endAddr); void PrecompileFunctions(); From 0ee058320a940d23acdabdf4b871d236bf32d680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Mar 2018 23:38:06 +0100 Subject: [PATCH 268/291] Pass new vulkan validation layers. Fix math in FindTransferFramebuffers. --- GPU/Common/FramebufferCommon.cpp | 4 ++-- ext/native/thin3d/VulkanRenderManager.h | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index c00afc1a26..91b339b7a0 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -1355,7 +1355,7 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst // Some games use mismatching bitdepths. But make sure the stride matches. // If it doesn't, generally this means we detected the framebuffer with too large a height. - bool match = yOffset < dstYOffset && yOffset < vfb->height; + bool match = yOffset < dstYOffset && (int)yOffset <= (int)vfb->height - dstHeight; if (match && vfb_byteStride != byteStride) { // Grand Knights History copies with a mismatching stride but a full line at a time. // Makes it hard to detect the wrong transfers in e.g. God of War. @@ -1385,7 +1385,7 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst const u32 byteOffset = srcBasePtr - vfb_address; const u32 byteStride = srcStride * bpp; const u32 yOffset = byteOffset / byteStride; - bool match = yOffset < srcYOffset && yOffset < vfb->height; + bool match = yOffset < srcYOffset && (int)yOffset <= (int)vfb->height - srcHeight; if (match && vfb_byteStride != byteStride) { if (width != srcStride || (byteStride * height != vfb_byteStride && byteStride * height != vfb_byteWidth)) { match = false; diff --git a/ext/native/thin3d/VulkanRenderManager.h b/ext/native/thin3d/VulkanRenderManager.h index 87de896d4f..f27de5d85d 100644 --- a/ext/native/thin3d/VulkanRenderManager.h +++ b/ext/native/thin3d/VulkanRenderManager.h @@ -12,6 +12,7 @@ #include "Common/Vulkan/VulkanContext.h" #include "math/dataconv.h" +#include "math/math_util.h" #include "thin3d/DataFormat.h" #include "thin3d/VulkanQueueRunner.h" @@ -117,7 +118,14 @@ public: void SetViewport(const VkViewport &vp) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER); VkRenderData data{ VKRRenderCommand::VIEWPORT }; - data.viewport.vp = vp; + data.viewport.vp.x = vp.x; + data.viewport.vp.y = vp.y; + data.viewport.vp.width = vp.width; + data.viewport.vp.height = vp.height; + // We can't allow values outside this range unless we use VK_EXT_depth_range_unrestricted. + // Sometimes state mapping produces 65536/65535 which is slightly outside. + data.viewport.vp.maxDepth = clamp_value(vp.maxDepth, 0.0f, 1.0f); + data.viewport.vp.minDepth = clamp_value(vp.minDepth, 0.0f, 1.0f); curRenderStep_->commands.push_back(data); } From a966403defc748cf5f1797587624347aedd2c13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Mar 2018 23:42:10 +0100 Subject: [PATCH 269/291] Add another SDL game controller config, fixing #10724 --- assets/gamecontrollerdb.txt | 1 + assets/lang | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/gamecontrollerdb.txt b/assets/gamecontrollerdb.txt index 8b1e8ac772..803eb62bca 100644 --- a/assets/gamecontrollerdb.txt +++ b/assets/gamecontrollerdb.txt @@ -185,3 +185,4 @@ bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,b 03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5, 05000000c82d00002038000000010000,8Bitdo NES30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b2,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4, 030000005e040000a102000000010000,Xbox 360 Wireless Receiver,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpdown:b14,dpleft:b11,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5, +050000004c050000cc09000001000000,Sony DualShock V2 Wireless Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, diff --git a/assets/lang b/assets/lang index d0e02dbcf9..465f6bc726 160000 --- a/assets/lang +++ b/assets/lang @@ -1 +1 @@ -Subproject commit d0e02dbcf91696daa996d7dd7ffe95d8a3443afa +Subproject commit 465f6bc726cdc0e6fe186db6efe63fa09cefdc9b From ad42ec54734ba7f35252824ad4f55d6ce49442cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Mar 2018 23:57:50 +0100 Subject: [PATCH 270/291] Inner interpreter: Add support for the Gran Turismo hack. --- GPU/GPUCommon.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index b14d11ae01..c94dac9918 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1391,8 +1391,9 @@ void GPUCommon::Execute_End(u32 op, u32 diff) { } void GPUCommon::Execute_TexLevel(u32 op, u32 diff) { - if (diff == 0xFFFFFFFF) return; - + // TODO: If you change the rules here, don't forget to update the inner interpreter in Execute_Prim. + if (diff == 0xFFFFFFFF) + return; gstate.texlevel ^= diff; if (gstate.getTexLevelMode() != GE_TEXLEVEL_MODE_AUTO && (0x00FF0000 & gstate.texlevel) != 0) { Flush(); @@ -1581,6 +1582,13 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { gstate.cmdmem[GE_CMD_TEXSCALEV] = data; gstate_c.uv.vScale = getFloat24(data); break; + case GE_CMD_TEXLEVEL: + // Same Gran Turismo hack from Execute_TexLevel + if ((data & 3) != GE_TEXLEVEL_MODE_AUTO && (0x00FF0000 & data) != 0) { + goto bail; + } + gstate.cmdmem[GE_CMD_TEXLEVEL] = data; + break; case GE_CMD_CALL: { // A bone matrix probably. If not we bail. From 648b4eac5130bf589164bef6ae3fc128d36be65c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 18 Mar 2018 09:42:05 +0100 Subject: [PATCH 271/291] Shrink the vertexCount field in DeferredDrawCall to the 16 bits required. --- GPU/Common/DrawEngineCommon.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 140aee1499..d3c64d2227 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -139,7 +139,7 @@ protected: void *inds; u8 indexType; s8 prim; - u32 vertexCount; + u16 vertexCount; u16 indexLowerBound; u16 indexUpperBound; UVScale uvScale; From 33a1e6a080c00d644a5705228182eb25da1b1379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 18 Mar 2018 09:43:13 +0100 Subject: [PATCH 272/291] Vulkan Clear-renderpass merging: If a copy step is found that reads from the affected buffer, don't merge the clear into the later renderpass. --- ext/native/thin3d/VulkanQueueRunner.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 1206b74e5a..6e1f7380c0 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -286,6 +286,11 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vectorstepType = VKRStepType::RENDER_SKIP; break; + } else if (steps[i]->stepType == VKRStepType::COPY && + steps[i]->copy.src == steps[j]->render.framebuffer) { + // Can't eliminate the clear if a game copies from it before it's + // rendered to. However this should be rare. + break; } } } @@ -445,7 +450,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c } } - // Don't execute empty renderpasses. + // Don't execute empty renderpasses that keep the contents. if (step.commands.empty() && step.render.color == VKRRenderPassAction::KEEP && step.render.depth == VKRRenderPassAction::KEEP && step.render.stencil == VKRRenderPassAction::KEEP) { // Nothing to do. return; From f43935b030fa0c4188513dc5a80a0bee5ba856c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Mar 2018 12:26:55 +0100 Subject: [PATCH 273/291] Merge framebuffer layout pre-transitions into render pass subpass dependencies. With this, drivers should be able to completely get rid of layout transitions into render passes that use CLEAR, at least. --- ext/native/thin3d/VulkanQueueRunner.cpp | 126 ++++++++++++------------ ext/native/thin3d/VulkanQueueRunner.h | 5 +- ext/native/thin3d/VulkanRenderManager.h | 6 +- 3 files changed, 70 insertions(+), 67 deletions(-) diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 6e1f7380c0..6b990bdf55 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -150,8 +150,8 @@ void VulkanQueueRunner::InitBackbufferRenderPass() { assert(res == VK_SUCCESS); } -VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction) { - RPKey key{ colorLoadAction, depthLoadAction, stencilLoadAction }; +VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction, VkImageLayout prevColorLayout, VkImageLayout prevDepthLayout) { + RPKey key{ colorLoadAction, depthLoadAction, stencilLoadAction, prevColorLayout, prevDepthLayout }; auto pass = renderPasses_.Get(key); if (pass) { return pass; @@ -179,7 +179,7 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio attachments[0].initialLayout = VK_IMAGE_LAYOUT_GENERAL; attachments[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL; // TODO: Look into auto-transitioning to SAMPLED when appropriate. #else - attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[0].initialLayout = prevColorLayout; attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // TODO: Look into auto-transitioning to SAMPLED when appropriate. #endif attachments[0].flags = 0; @@ -214,7 +214,7 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio attachments[1].initialLayout = VK_IMAGE_LAYOUT_GENERAL; attachments[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL; #else - attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].initialLayout = prevDepthLayout; attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; #endif attachments[1].flags = 0; @@ -239,12 +239,65 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio subpass.preserveAttachmentCount = 0; subpass.pPreserveAttachments = nullptr; + VkSubpassDependency dep{}; + dep.srcSubpass = VK_SUBPASS_EXTERNAL; + dep.dstSubpass = 0; + dep.dependencyFlags = 0; + + switch (prevColorLayout) { + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + // Already the right color layout. Unclear that we need to do a lot here.. + break; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + dep.srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; + dep.srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + dep.srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; + dep.srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + dep.srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; + dep.srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + default: + _dbg_assert_msg_(G3D, false, "GetRenderPass: Unexpected color layout %d", (int)prevColorLayout); + break; + } + + switch (prevDepthLayout) { + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + // Already the right depth layout. Unclear that we need to do a lot here.. + break; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + dep.srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; + dep.srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + dep.srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; + dep.srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + dep.srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; + dep.srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + default: + _dbg_assert_msg_(G3D, false, "PerformBindRT: Unexpected depth layout %d", (int)prevDepthLayout); + break; + } + dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dep.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + VkRenderPassCreateInfo rp{ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO }; rp.attachmentCount = 2; rp.pAttachments = attachments; rp.subpassCount = 1; rp.pSubpasses = &subpass; - rp.dependencyCount = 0; + + if (dep.srcAccessMask) { + rp.dependencyCount = 1; + rp.pDependencies = &dep; + } VkResult res = vkCreateRenderPass(vulkan_->GetDevice(), &rp, nullptr, &pass); _assert_(res == VK_SUCCESS); @@ -605,67 +658,12 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step framebuf = fb->framebuf; w = fb->width; h = fb->height; - // Now, if the image needs transitioning, let's transition. - // The backbuffer does not, that's handled by VulkanContext. - if (step.render.framebuffer->color.layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { - VkAccessFlags srcAccessMask = 0; - VkPipelineStageFlags srcStage = 0; - switch (fb->color.layout) { - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - srcStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - default: - _dbg_assert_msg_(G3D, false, "PerformBindRT: Unexpected color layout %d", (int)fb->color.layout); - break; - } - // Due to a known bug in the Mali driver, pass the level count explicitly. - TransitionImageLayout2(cmd, fb->color.image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, - fb->color.layout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - srcStage, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - srcAccessMask, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT); - fb->color.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } - if (fb->depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { - VkAccessFlags srcAccessMask = 0; - VkPipelineStageFlags srcStage = 0; + renderPass = GetRenderPass(step.render.color, step.render.depth, step.render.stencil, fb->color.layout, fb->depth.layout); + // We now do any layout pretransitions as part of the render pass. + fb->color.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + fb->depth.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - switch (fb->depth.layout) { - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - srcStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - default: - _dbg_assert_msg_(G3D, false, "PerformBindRT: Unexpected depth layout %d", (int)fb->color.layout); - break; - } - - // Due to a known bug in the Mali driver, pass the level count explicitly (last param). - TransitionImageLayout2(cmd, fb->depth.image, 0, 1, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, - fb->depth.layout, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - srcStage, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - srcAccessMask, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT); - fb->depth.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - } - - renderPass = GetRenderPass(step.render.color, step.render.depth, step.render.stencil); if (step.render.color == VKRRenderPassAction::CLEAR) { Uint8x4ToFloat4(clearVal[0].color.float32, step.render.clearColor); numClearVals = 1; diff --git a/ext/native/thin3d/VulkanQueueRunner.h b/ext/native/thin3d/VulkanQueueRunner.h index f10326ff95..31afe09e4a 100644 --- a/ext/native/thin3d/VulkanQueueRunner.h +++ b/ext/native/thin3d/VulkanQueueRunner.h @@ -161,7 +161,8 @@ public: VkRenderPass GetBackbufferRenderPass() const { return backbufferRenderPass_; } - VkRenderPass GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction); + VkRenderPass GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction, + VkImageLayout prevColorLayout, VkImageLayout prevDepthLayout); inline int RPIndex(VKRRenderPassAction color, VKRRenderPassAction depth) { return (int)depth * 3 + (int)color; @@ -202,6 +203,8 @@ private: VKRRenderPassAction colorAction; VKRRenderPassAction depthAction; VKRRenderPassAction stencilAction; + VkImageLayout prevColorLayout; + VkImageLayout prevDepthLayout; }; // Renderpasses, all combinations of preserving or clearing or dont-care-ing fb contents. diff --git a/ext/native/thin3d/VulkanRenderManager.h b/ext/native/thin3d/VulkanRenderManager.h index f27de5d85d..a57a21c02c 100644 --- a/ext/native/thin3d/VulkanRenderManager.h +++ b/ext/native/thin3d/VulkanRenderManager.h @@ -205,14 +205,16 @@ public: VkCommandBuffer GetInitCmd(); VkRenderPass GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction) { - return queueRunner_.GetRenderPass(colorLoadAction, depthLoadAction, stencilLoadAction); + return queueRunner_.GetRenderPass(colorLoadAction, depthLoadAction, stencilLoadAction, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); } VkRenderPass GetBackbufferRenderPass() { return queueRunner_.GetBackbufferRenderPass(); } VkRenderPass GetCompatibleRenderPass() { if (curRenderStep_ && curRenderStep_->render.framebuffer != nullptr) { - return queueRunner_.GetRenderPass(VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR); + return queueRunner_.GetRenderPass(VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); } else { return queueRunner_.GetBackbufferRenderPass(); } From 216bab8a4a716a22c91aa185721800f844f3bb5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Mar 2018 19:40:27 +0100 Subject: [PATCH 274/291] Vulkan: Fix a barrier to be more permissive, there's no outstanding writes from the GPU to wait for. --- Common/Vulkan/VulkanImage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index a7244d6dde..70b561b036 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -106,7 +106,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: TransitionImageLayout2(cmd, image_, 0, numMips, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT); break; default: From 6d5f0665fe1f1a7e77b4f93ecd6c60e8b945a7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 18 Mar 2018 11:19:10 +0100 Subject: [PATCH 275/291] Add a super focused workaround for the Mali bug, see #10723 Minimizes the performance penalty. --- ext/native/thin3d/VulkanQueueRunner.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 6b990bdf55..02f9cae209 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -248,6 +248,11 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: // Already the right color layout. Unclear that we need to do a lot here.. break; + case VK_IMAGE_LAYOUT_GENERAL: + // We came from the Mali workaround, and are transitioning back to COLOR_ATTACHMENT_OPTIMAL. + dep.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dep.srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + break; case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: dep.srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; dep.srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; @@ -659,6 +664,22 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step w = fb->width; h = fb->height; + // Mali driver on S8 (Android O) and S9 mishandles renderpasses that do just a clear + // and then no draw calls. Memory transaction elimination gets mis-flagged or something. + // To avoid this, we transition to GENERAL and back in this case (ARM-approved workaround). + // See pull request #10723. + bool maliBugWorkaround = step.render.numDraws == 0 && + step.render.color == VKRRenderPassAction::CLEAR && + vulkan_->GetPhysicalDeviceProperties().driverVersion == 0xaa9c4b29; + if (maliBugWorkaround) { + TransitionImageLayout2(cmd, step.render.framebuffer->color.image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, + fb->color.layout, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); + fb->color.layout = VK_IMAGE_LAYOUT_GENERAL; + } + renderPass = GetRenderPass(step.render.color, step.render.depth, step.render.stencil, fb->color.layout, fb->depth.layout); // We now do any layout pretransitions as part of the render pass. fb->color.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; From b7fa253192c64ce3f911799b44bc8e475b4572c7 Mon Sep 17 00:00:00 2001 From: crocket <748856+crocket@users.noreply.github.com> Date: Sun, 18 Mar 2018 19:24:52 +0900 Subject: [PATCH 276/291] Map SDL controller's `back` button to Sony DualShock 4 V2's share button It turns out that `back` button is actually `select` button on PSP. I confirmed this by clicking touchpad in a game. `select` button maps to `share` button on Sony DualShock 4 V2. --- assets/gamecontrollerdb.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/gamecontrollerdb.txt b/assets/gamecontrollerdb.txt index 803eb62bca..7201505468 100644 --- a/assets/gamecontrollerdb.txt +++ b/assets/gamecontrollerdb.txt @@ -177,7 +177,7 @@ bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,b 050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, 030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, 05000000ac0500003232000001000000,VR-BOX,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5, -030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, +030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, 030000004c050000cc09000011810000,Sony Interactive Entertainment Wireless Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, 050000004c050000cc09000000810000,Wireless Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, 030000004c0500006802000011810000,Sony PLAYSTATION(R)3 Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, @@ -185,4 +185,4 @@ bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,b 03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5, 05000000c82d00002038000000010000,8Bitdo NES30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b2,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4, 030000005e040000a102000000010000,Xbox 360 Wireless Receiver,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpdown:b14,dpleft:b11,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5, -050000004c050000cc09000001000000,Sony DualShock V2 Wireless Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, +050000004c050000cc09000001000000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, From 2d3655ea231421a4586fb39d9deff4340e16cf94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 18 Mar 2018 12:03:00 +0100 Subject: [PATCH 277/291] Vulkan: Get rid of more explicit barriers by merging the finalLayout color transitions into renderpasses. --- ext/native/thin3d/VulkanQueueRunner.cpp | 138 +++++++++++++----------- ext/native/thin3d/VulkanQueueRunner.h | 4 +- ext/native/thin3d/VulkanRenderManager.h | 4 +- 3 files changed, 81 insertions(+), 65 deletions(-) diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 02f9cae209..2bbf6c2705 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -150,8 +150,8 @@ void VulkanQueueRunner::InitBackbufferRenderPass() { assert(res == VK_SUCCESS); } -VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction, VkImageLayout prevColorLayout, VkImageLayout prevDepthLayout) { - RPKey key{ colorLoadAction, depthLoadAction, stencilLoadAction, prevColorLayout, prevDepthLayout }; +VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction, VkImageLayout prevColorLayout, VkImageLayout prevDepthLayout, VkImageLayout finalColorLayout) { + RPKey key{ colorLoadAction, depthLoadAction, stencilLoadAction, prevColorLayout, prevDepthLayout, finalColorLayout }; auto pass = renderPasses_.Get(key); if (pass) { return pass; @@ -177,10 +177,10 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; #ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR attachments[0].initialLayout = VK_IMAGE_LAYOUT_GENERAL; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL; // TODO: Look into auto-transitioning to SAMPLED when appropriate. + attachments[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL; #else attachments[0].initialLayout = prevColorLayout; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // TODO: Look into auto-transitioning to SAMPLED when appropriate. + attachments[0].finalLayout = finalColorLayout; #endif attachments[0].flags = 0; @@ -221,11 +221,11 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio VkAttachmentReference color_reference{}; color_reference.attachment = 0; - color_reference.layout = attachments[0].finalLayout; + color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; VkAttachmentReference depth_reference{}; depth_reference.attachment = 1; - depth_reference.layout = attachments[1].finalLayout; + depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; VkSubpassDescription subpass{}; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; @@ -239,31 +239,28 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio subpass.preserveAttachmentCount = 0; subpass.pPreserveAttachments = nullptr; - VkSubpassDependency dep{}; - dep.srcSubpass = VK_SUBPASS_EXTERNAL; - dep.dstSubpass = 0; - dep.dependencyFlags = 0; - + VkSubpassDependency deps[2]{}; + int numDeps = 0; switch (prevColorLayout) { case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: // Already the right color layout. Unclear that we need to do a lot here.. break; case VK_IMAGE_LAYOUT_GENERAL: // We came from the Mali workaround, and are transitioning back to COLOR_ATTACHMENT_OPTIMAL. - dep.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dep.srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + deps[numDeps].srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - dep.srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; - dep.srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + deps[numDeps].srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; + deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - dep.srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; - dep.srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + deps[numDeps].srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; + deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - dep.srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; - dep.srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + deps[numDeps].srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; + deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; break; default: _dbg_assert_msg_(G3D, false, "GetRenderPass: Unexpected color layout %d", (int)prevColorLayout); @@ -275,23 +272,60 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio // Already the right depth layout. Unclear that we need to do a lot here.. break; case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - dep.srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; - dep.srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + deps[numDeps].srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; + deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - dep.srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; - dep.srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + deps[numDeps].srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; + deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - dep.srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; - dep.srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + deps[numDeps].srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; + deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; break; default: _dbg_assert_msg_(G3D, false, "PerformBindRT: Unexpected depth layout %d", (int)prevDepthLayout); break; } - dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dep.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + if (deps[numDeps].srcAccessMask) { + deps[numDeps].srcSubpass = VK_SUBPASS_EXTERNAL; + deps[numDeps].dstSubpass = 0; + deps[numDeps].dependencyFlags = 0; + deps[numDeps].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + deps[numDeps].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + numDeps++; + } + + // And the final transition. + // Don't need to transition it if VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL. + switch (finalColorLayout) { + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + deps[numDeps].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + deps[numDeps].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + deps[numDeps].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + deps[numDeps].dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + deps[numDeps].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + deps[numDeps].dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_UNDEFINED: + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + // Nothing to do. + break; + } + + if (deps[numDeps].dstAccessMask) { + deps[numDeps].srcSubpass = 0; + deps[numDeps].dstSubpass = VK_SUBPASS_EXTERNAL; + deps[numDeps].dependencyFlags = 0; + deps[numDeps].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + deps[numDeps].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + numDeps++; + } VkRenderPassCreateInfo rp{ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO }; rp.attachmentCount = 2; @@ -299,9 +333,9 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio rp.subpassCount = 1; rp.pSubpasses = &subpass; - if (dep.srcAccessMask) { - rp.dependencyCount = 1; - rp.pDependencies = &dep; + if (numDeps) { + rp.dependencyCount = numDeps; + rp.pDependencies = deps; } VkResult res = vkCreateRenderPass(vulkan_->GetDevice(), &rp, nullptr, &pass); @@ -319,6 +353,12 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vectorstepType == VKRStepType::RENDER && + steps[j]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { + // Just leave it at color_optimal. + steps[j]->render.finalColorLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } + if (steps.size() > 1 && steps[j]->stepType == VKRStepType::RENDER && steps[j]->render.numDraws == 0 && steps[j]->render.color == VKRRenderPassAction::CLEAR && @@ -616,37 +656,8 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c } vkCmdEndRenderPass(cmd); - // Transition the framebuffer if requested. - // Don't need to transition it if VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL. - if (fb && step.render.finalColorLayout != VK_IMAGE_LAYOUT_UNDEFINED && step.render.finalColorLayout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { - VkAccessFlags srcAccessMask = 0; - VkAccessFlags dstAccessMask = 0; - switch (fb->color.layout) { - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - break; - default: - Crash(); - } - switch (step.render.finalColorLayout) { - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - break; - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; - break; - default: - Crash(); - } - // we're between passes so it's OK. - // ARM Best Practices guide recommends these stage bits. - TransitionImageLayout2(cmd, fb->color.image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, - fb->color.layout, step.render.finalColorLayout, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - srcAccessMask, dstAccessMask); + // The renderpass handles the layout transition. + if (fb) { fb->color.layout = step.render.finalColorLayout; } } @@ -680,7 +691,10 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step fb->color.layout = VK_IMAGE_LAYOUT_GENERAL; } - renderPass = GetRenderPass(step.render.color, step.render.depth, step.render.stencil, fb->color.layout, fb->depth.layout); + renderPass = GetRenderPass( + step.render.color, step.render.depth, step.render.stencil, + fb->color.layout, fb->depth.layout, step.render.finalColorLayout); + // We now do any layout pretransitions as part of the render pass. fb->color.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; fb->depth.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; diff --git a/ext/native/thin3d/VulkanQueueRunner.h b/ext/native/thin3d/VulkanQueueRunner.h index 31afe09e4a..ff536a803a 100644 --- a/ext/native/thin3d/VulkanQueueRunner.h +++ b/ext/native/thin3d/VulkanQueueRunner.h @@ -162,7 +162,7 @@ public: return backbufferRenderPass_; } VkRenderPass GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction, - VkImageLayout prevColorLayout, VkImageLayout prevDepthLayout); + VkImageLayout prevColorLayout, VkImageLayout prevDepthLayout, VkImageLayout finalColorLayout); inline int RPIndex(VKRRenderPassAction color, VKRRenderPassAction depth) { return (int)depth * 3 + (int)color; @@ -205,6 +205,8 @@ private: VKRRenderPassAction stencilAction; VkImageLayout prevColorLayout; VkImageLayout prevDepthLayout; + VkImageLayout finalColorLayout; + // TODO: Also pre-transition depth, for copies etc. }; // Renderpasses, all combinations of preserving or clearing or dont-care-ing fb contents. diff --git a/ext/native/thin3d/VulkanRenderManager.h b/ext/native/thin3d/VulkanRenderManager.h index a57a21c02c..de4f192b01 100644 --- a/ext/native/thin3d/VulkanRenderManager.h +++ b/ext/native/thin3d/VulkanRenderManager.h @@ -206,7 +206,7 @@ public: VkRenderPass GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction) { return queueRunner_.GetRenderPass(colorLoadAction, depthLoadAction, stencilLoadAction, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); } VkRenderPass GetBackbufferRenderPass() { return queueRunner_.GetBackbufferRenderPass(); @@ -214,7 +214,7 @@ public: VkRenderPass GetCompatibleRenderPass() { if (curRenderStep_ && curRenderStep_->render.framebuffer != nullptr) { return queueRunner_.GetRenderPass(VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); } else { return queueRunner_.GetBackbufferRenderPass(); } From 3e7723ea6d4e94d327fe1e53e0dc4a70c00a3d4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 18 Mar 2018 12:09:02 +0100 Subject: [PATCH 278/291] Vulkan: Use finalLayout to optimize away barriers before framebuffer copies. --- ext/native/thin3d/VulkanRenderManager.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 068b3419e9..0128cc430d 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -646,6 +646,22 @@ void VulkanRenderManager::CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, _dbg_assert_msg_(G3D, dstPos.x + srcRect.extent.width <= (uint32_t)dst->width, "dstPos + extent x > width"); _dbg_assert_msg_(G3D, dstPos.y + srcRect.extent.height <= (uint32_t)dst->height, "dstPos + extent y > height"); + for (int i = (int)steps_.size() - 1; i >= 0; i--) { + if (steps_[i]->stepType == VKRStepType::RENDER) { + if (steps_[i]->render.framebuffer == src) { + if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { + steps_[i]->render.finalColorLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + break; + } + } else if (steps_[i]->render.framebuffer == dst) { + if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { + steps_[i]->render.finalColorLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + break; + } + } + } + } + VKRStep *step = new VKRStep{ VKRStepType::COPY }; step->copy.aspectMask = aspectMask; @@ -699,10 +715,6 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in steps_[i]->render.finalColorLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; break; } - else if (steps_[i]->render.finalColorLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - Crash(); - // May need to shadow the framebuffer if we re-order passes later. - } } } From 1dabccb453746ef2c5f0ef5b2590c33833129215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 18 Mar 2018 13:14:20 +0100 Subject: [PATCH 279/291] Vulkan: Minor logic fixes in the transition elimination --- ext/native/thin3d/VulkanRenderManager.cpp | 25 ++++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 0128cc430d..3c325bf288 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -647,18 +647,19 @@ void VulkanRenderManager::CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, _dbg_assert_msg_(G3D, dstPos.y + srcRect.extent.height <= (uint32_t)dst->height, "dstPos + extent y > height"); for (int i = (int)steps_.size() - 1; i >= 0; i--) { - if (steps_[i]->stepType == VKRStepType::RENDER) { - if (steps_[i]->render.framebuffer == src) { - if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { - steps_[i]->render.finalColorLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - break; - } - } else if (steps_[i]->render.framebuffer == dst) { - if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { - steps_[i]->render.finalColorLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - break; - } + if (steps_[i]->stepType == VKRStepType::RENDER && steps_[i]->render.framebuffer == src) { + if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { + steps_[i]->render.finalColorLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; } + break; + } + } + for (int i = (int)steps_.size() - 1; i >= 0; i--) { + if (steps_[i]->stepType == VKRStepType::RENDER && steps_[i]->render.framebuffer == dst) { + if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { + steps_[i]->render.finalColorLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + } + break; } } @@ -713,8 +714,8 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in // If this framebuffer was rendered to earlier in this frame, make sure to pre-transition it to the correct layout. if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { steps_[i]->render.finalColorLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - break; } + break; } } From 8f87a9f5c5197d5eb609d12ab5d6aaaf124a132c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 19 Mar 2018 10:55:06 +0100 Subject: [PATCH 280/291] Vulkan: De-duplicate pipelines when storing cache The new variety of renderpasses with different transitions causes duplication. Hopefully drivers are smart enough to re-use work between similar pipelines as much as possible... --- Common/Vulkan/VulkanContext.h | 7 ++++--- Common/Vulkan/VulkanImage.cpp | 6 ++++++ GPU/Vulkan/PipelineManagerVulkan.cpp | 23 +++++++++++++++++------ GPU/Vulkan/PipelineManagerVulkan.h | 6 ++++++ GPU/Vulkan/ShaderManagerVulkan.cpp | 2 +- 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index 3bb4080694..ac4d98148f 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -135,10 +135,11 @@ public: bool EnableDeviceExtension(const char *extension); VkResult CreateDevice(); - const std::string &InitError() { return init_error_; } + const std::string &InitError() const { return init_error_; } - VkDevice GetDevice() { return device_; } - VkInstance GetInstance() { return instance_; } + VkDevice GetDevice() const { return device_; } + VkInstance GetInstance() const { return instance_; } + uint32_t GetFlags() const { return flags_; } VulkanDeleteList &Delete() { return globalDeleteList_; } diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index 70b561b036..4e8b841517 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -58,6 +58,12 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; } + // The graphics debugger always "needs" TRANSFER_SRC but in practice doesn't matter - + // unless validation is on. So let's only force it on when being validated, for now. + if (vulkan_->GetFlags() & VULKAN_FLAG_VALIDATE) { + image_create_info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + } + VkResult res = vkCreateImage(vulkan_->GetDevice(), &image_create_info, NULL, &image_); if (res != VK_SUCCESS) { _assert_(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 6e9a62aeb9..70870997fb 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "profiler/profiler.h" @@ -526,12 +527,14 @@ void PipelineManagerVulkan::SaveCache(FILE *file, bool saveRawPipelineCache, Sha } size_t seekPosOnFailure = ftell(file); - // Write the number of pipelines. - size = (uint32_t)pipelines_.size(); - fwrite(&size, sizeof(size), 1, file); bool failed = false; int count = 0; + // Since we don't include the full pipeline key, there can be duplicates, + // caused by things like switching from buffered to non-buffered rendering. + // Make sure the set of pipelines we write is "unique". + std::set keys; + pipelines_.Iterate([&](const VulkanPipelineKey &pkey, VulkanPipeline *value) { if (failed) return; @@ -550,10 +553,18 @@ void PipelineManagerVulkan::SaveCache(FILE *file, bool saveRawPipelineCache, Sha // NOTE: This is not a vtype, but a decoded vertex format. key.vtxFmtId = pkey.vtxFmtId; } - fwrite(&key, sizeof(key), 1, file); - count++; + keys.insert(key); }); + // Write the number of pipelines. + size = (uint32_t)keys.size(); + fwrite(&size, sizeof(size), 1, file); + + // Write the pipelines. + for (auto &key : keys) { + fwrite(&key, sizeof(key), 1, file); + } + if (failed) { ERROR_LOG(G3D, "Failed to write pipeline cache, some shader was missing"); // Write a zero in the right place so it doesn't try to load the pipelines next time. @@ -562,7 +573,7 @@ void PipelineManagerVulkan::SaveCache(FILE *file, bool saveRawPipelineCache, Sha fwrite(&size, sizeof(size), 1, file); return; } - NOTICE_LOG(G3D, "Saved Vulkan pipeline ID cache (%d pipelines).", (int)count); + NOTICE_LOG(G3D, "Saved Vulkan pipeline ID cache (%d unique pipelines/%d).", (int)keys.size(), (int)pipelines_.size()); } bool PipelineManagerVulkan::LoadCache(FILE *file, bool loadRawPipelineCache, ShaderManagerVulkan *shaderManager, DrawEngineCommon *drawEngine, VkPipelineLayout layout, VkRenderPass renderPass) { diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index 6cf98c7ed4..60a0582c38 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -17,6 +17,7 @@ #pragma once +#include #include "Common/Hashmaps.h" #include "GPU/Common/VertexDecoderCommon.h" @@ -60,6 +61,11 @@ struct StoredVulkanPipelineKey { FShaderID fShaderID; uint32_t vtxFmtId; bool useHWTransform; + + // For std::set. Better zero-initialize the struct properly for this to work. + bool operator < (const StoredVulkanPipelineKey &other) const { + return memcmp(this, &other, sizeof(*this)) < 0; + } }; enum PipelineFlags { diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index b753ebd19a..666f47aa52 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -350,7 +350,7 @@ VulkanFragmentShader *ShaderManagerVulkan::GetFragmentShaderFromModule(VkShaderM // instantaneous. #define CACHE_HEADER_MAGIC 0xff51f420 -#define CACHE_VERSION 5 +#define CACHE_VERSION 6 struct VulkanCacheHeader { uint32_t magic; uint32_t version; From 3e5757d7d754b7836445d7adcec521d3f3289f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 19 Mar 2018 11:19:01 +0100 Subject: [PATCH 281/291] Minor improvement in pipeline-to-string (debug) --- GPU/Vulkan/PipelineManagerVulkan.cpp | 84 ++++++++++++++++++---------- GPU/Vulkan/PipelineManagerVulkan.h | 1 + 2 files changed, 55 insertions(+), 30 deletions(-) diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 70870997fb..59c08b3300 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -313,6 +313,10 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layo PROFILE_THIS_SCOPE("pipelinebuild"); + std::string temp; + key.ToString(&temp); + NOTICE_LOG(G3D, "Creating: %s", temp.c_str()); + VulkanPipeline *pipeline = CreateVulkanPipeline( vulkan_->GetDevice(), pipelineCache_, layout, renderPass, rasterKey, decFmt, vs, fs, useHwTransform, lineWidth_); @@ -367,6 +371,25 @@ static const char *const compareOps[8] = { "ALWAYS", }; +static const char *const logicOps[] = { + "CLEAR", + "AND", + "AND_REV", + "COPY", + "AND_INV", + "NOOP", + "XOR", + "OR", + "NOR", + "EQUIV", + "INVERT", + "OR_REV", + "COPY_INV", + "OR_INV", + "NAND", + "SET", +}; + static const char *const stencilOps[8] = { "KEEP", "ZERO", @@ -412,27 +435,31 @@ std::string PipelineManagerVulkan::DebugGetObjectString(std::string id, DebugSha return ""; } + std::string str = pipelineKey.GetDescription(stringType); + return StringFromFormat("%p: %s", iter, str.c_str()); +} + +std::string VulkanPipelineKey::GetDescription(DebugShaderStringType stringType) const { switch (stringType) { case SHADER_STRING_SHORT_DESC: { std::stringstream str; - str << topologies[pipelineKey.raster.topology] << " "; - if (pipelineKey.raster.blendEnable) { - str << "Blend("; - str << "C:" << blendOps[pipelineKey.raster.blendOpColor] << "/" - << blendFactors[pipelineKey.raster.srcColor] << ":" << blendFactors[pipelineKey.raster.destColor] << " "; - if (pipelineKey.raster.blendOpAlpha != VK_BLEND_OP_ADD || - pipelineKey.raster.srcAlpha != VK_BLEND_FACTOR_ONE || - pipelineKey.raster.destAlpha != VK_BLEND_FACTOR_ZERO) { - str << "A:" << blendOps[pipelineKey.raster.blendOpAlpha] << "/" - << blendFactors[pipelineKey.raster.srcColor] << ":" << blendFactors[pipelineKey.raster.destColor] << " "; + str << topologies[raster.topology] << " "; + if (raster.blendEnable) { + str << "Blend(C:" << blendOps[raster.blendOpColor] << "/" + << blendFactors[raster.srcColor] << ":" << blendFactors[raster.destColor] << " "; + if (raster.blendOpAlpha != VK_BLEND_OP_ADD || + raster.srcAlpha != VK_BLEND_FACTOR_ONE || + raster.destAlpha != VK_BLEND_FACTOR_ZERO) { + str << "A:" << blendOps[raster.blendOpAlpha] << "/" + << blendFactors[raster.srcColor] << ":" << blendFactors[raster.destColor] << " "; } str << ") "; } - if (pipelineKey.raster.colorWriteMask != 0xF) { + if (raster.colorWriteMask != 0xF) { str << "Mask("; for (int i = 0; i < 4; i++) { - if (pipelineKey.raster.colorWriteMask & (1 << i)) { + if (raster.colorWriteMask & (1 << i)) { str << "RGBA"[i]; } else { str << "_"; @@ -440,37 +467,34 @@ std::string PipelineManagerVulkan::DebugGetObjectString(std::string id, DebugSha } str << ") "; } - if (pipelineKey.raster.depthTestEnable) { + if (raster.depthTestEnable) { str << "Depth("; - if (pipelineKey.raster.depthWriteEnable) + if (raster.depthWriteEnable) str << "W, "; - if (pipelineKey.raster.depthCompareOp) - str << compareOps[pipelineKey.raster.depthCompareOp & 7]; + if (raster.depthCompareOp) + str << compareOps[raster.depthCompareOp & 7]; str << ") "; } - if (pipelineKey.raster.stencilTestEnable) { + if (raster.stencilTestEnable) { str << "Stencil("; - str << compareOps[pipelineKey.raster.stencilCompareOp & 7] << " "; - str << stencilOps[pipelineKey.raster.stencilPassOp & 7] << "/"; - str << stencilOps[pipelineKey.raster.stencilFailOp & 7] << "/"; - str << stencilOps[pipelineKey.raster.stencilDepthFailOp& 7]; + str << compareOps[raster.stencilCompareOp & 7] << " "; + str << stencilOps[raster.stencilPassOp & 7] << "/"; + str << stencilOps[raster.stencilFailOp & 7] << "/"; + str << stencilOps[raster.stencilDepthFailOp& 7]; str << ") "; } - if (pipelineKey.raster.logicOpEnable) { - str << "Logic("; - str << ") "; + if (raster.logicOpEnable) { + str << "Logic(" << logicOps[raster.logicOp & 15] << ") "; } - if (pipelineKey.useHWTransform) { + if (useHWTransform) { str << "HWX "; } - if (pipelineKey.vtxFmtId) { - str << "V("; - str << StringFromFormat("%08x", pipelineKey.vtxFmtId); // TODO: Format nicer. - str << ") "; + if (vtxFmtId) { + str << "V(" << StringFromFormat("%08x", vtxFmtId) << ") "; // TODO: Format nicer. } else { str << "SWX "; } - return StringFromFormat("%p: %s", iter, str.str().c_str()); + return str.str(); } case SHADER_STRING_SOURCE_CODE: diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index 60a0582c38..1ef673b9b7 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -53,6 +53,7 @@ struct VulkanPipelineKey { void FromString(const std::string &str) { memcpy(this, &str[0], sizeof(*this)); } + std::string GetDescription(DebugShaderStringType stringType) const; }; struct StoredVulkanPipelineKey { From 7ce5f8d29c2569ded84472907f201b2033316eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 19 Mar 2018 14:44:20 +0100 Subject: [PATCH 282/291] Delete some mistaken logging code --- GPU/Vulkan/PipelineManagerVulkan.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 59c08b3300..4e563b2066 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -313,10 +313,6 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layo PROFILE_THIS_SCOPE("pipelinebuild"); - std::string temp; - key.ToString(&temp); - NOTICE_LOG(G3D, "Creating: %s", temp.c_str()); - VulkanPipeline *pipeline = CreateVulkanPipeline( vulkan_->GetDevice(), pipelineCache_, layout, renderPass, rasterKey, decFmt, vs, fs, useHwTransform, lineWidth_); From 1888d828ece4ded36075374d4dc4d12a3a710e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 19 Mar 2018 17:33:08 +0100 Subject: [PATCH 283/291] Vulkan: Workaround for bug in Adreno shader compiler affecting color tests. This comparison should pretty much work as well as the old one, I believe, if not faster. Should help #10695 --- GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp b/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp index bc0dc0f633..38764ba7d3 100644 --- a/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp @@ -268,12 +268,13 @@ bool GenerateVulkanGLSLFragmentShader(const FShaderID &id, char *buffer) { if (enableColorTest) { if (colorTestAgainstZero) { // When testing against 0 (common), we can avoid some math. + // Have my doubts that this special case is actually worth it, but whatever. // 0.002 is approximately half of 1.0 / 255.0. if (colorTestFunc == GE_COMP_NOTEQUAL) { - WRITE(p, " if (v.r < 0.002 && v.g < 0.002 && v.b < 0.002) discard;\n"); + WRITE(p, " if (v.r + v.g + v.b < 0.002) discard;\n"); } else if (colorTestFunc != GE_COMP_NEVER) { // Anything else is a test for == 0. - WRITE(p, " if (v.r > 0.002 || v.g > 0.002 || v.b > 0.002) discard;\n"); + WRITE(p, " if (v.r + v.g + v.b > 0.002) discard;\n"); } else { // NEVER has been logged as used by games, although it makes little sense - statically failing. // Maybe we could discard the drawcall, but it's pretty rare. Let's just statically discard here. From f1359af0b05ca85afff8b77d20855be13922f787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 19 Mar 2018 17:46:58 +0100 Subject: [PATCH 284/291] Vulkan: Improve handling of shader compile failures (don't crash) --- GPU/Vulkan/DrawEngineVulkan.cpp | 4 ++-- GPU/Vulkan/PipelineManagerVulkan.cpp | 30 ++++++++++++++++++------- ext/native/thin3d/VulkanRenderManager.h | 1 + 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 6fdc1855b7..a394275262 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -774,7 +774,7 @@ void DrawEngineVulkan::DoFlush() { Draw::NativeObject object = g_Config.iRenderingMode != 0 ? Draw::NativeObject::FRAMEBUFFER_RENDERPASS : Draw::NativeObject::BACKBUFFER_RENDERPASS; VkRenderPass renderPass = (VkRenderPass)draw_->GetNativeObject(object); VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, renderPass, pipelineKey_, &dec_->decFmt, vshader, fshader, true); - if (!pipeline) { + if (!pipeline || !pipeline->pipeline) { // Already logged, let's bail out. return; } @@ -878,7 +878,7 @@ void DrawEngineVulkan::DoFlush() { Draw::NativeObject object = g_Config.iRenderingMode != 0 ? Draw::NativeObject::FRAMEBUFFER_RENDERPASS : Draw::NativeObject::BACKBUFFER_RENDERPASS; VkRenderPass renderPass = (VkRenderPass)draw_->GetNativeObject(object); VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, renderPass, pipelineKey_, &dec_->decFmt, vshader, fshader, false); - if (!pipeline) { + if (!pipeline || !pipeline->pipeline) { // Already logged, let's bail out. return; } diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 4e563b2066..15a06989d2 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -28,7 +28,8 @@ void PipelineManagerVulkan::Clear() { // store the keys. pipelines_.Iterate([&](const VulkanPipelineKey &key, VulkanPipeline *value) { - vulkan_->Delete().QueueDeletePipeline(value->pipeline); + if (value->pipeline) + vulkan_->Delete().QueueDeletePipeline(value->pipeline); delete value; }); @@ -116,6 +117,7 @@ static bool UsesBlendConstant(int factor) { static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pipelineCache, VkPipelineLayout layout, VkRenderPass renderPass, const VulkanPipelineRasterStateKey &key, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform, float lineWidth) { + PROFILE_THIS_SCOPE("pipelinebuild"); bool useBlendConstant = false; VkPipelineColorBlendAttachmentState blend0 = {}; @@ -209,7 +211,11 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip if (!ss[0].module || !ss[1].module) { ERROR_LOG(G3D, "Failed creating graphics pipeline - bad shaders"); - return nullptr; + // Create a placeholder to avoid creating over and over if shader compiler broken. + VulkanPipeline *nullPipeline = new VulkanPipeline(); + nullPipeline->pipeline = nullptr; + nullPipeline->flags = 0; + return nullPipeline; } VkPipelineInputAssemblyStateCreateInfo inputAssembly{ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; @@ -277,7 +283,11 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip if (result != VK_SUCCESS) { _assert_msg_(G3D, false, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result)); ERROR_LOG(G3D, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result)); - return nullptr; + // Create a placeholder to avoid creating over and over if something is broken. + VulkanPipeline *nullPipeline = new VulkanPipeline(); + nullPipeline->pipeline = nullptr; + nullPipeline->flags = 0; + return nullPipeline; } VulkanPipeline *vulkanPipeline = new VulkanPipeline(); @@ -311,14 +321,17 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layo if (iter) return iter; - PROFILE_THIS_SCOPE("pipelinebuild"); - VulkanPipeline *pipeline = CreateVulkanPipeline( vulkan_->GetDevice(), pipelineCache_, layout, renderPass, rasterKey, decFmt, vs, fs, useHwTransform, lineWidth_); - // Even if the result is nullptr, insert it so we don't try to create it repeatedly. pipelines_.Insert(key, pipeline); - return pipeline; + + // Don't return placeholder null pipelines. + if (pipeline && pipeline->pipeline) { + return pipeline; + } else { + return nullptr; + } } std::vector PipelineManagerVulkan::DebugGetObjectIDs(DebugShaderType type) { @@ -510,7 +523,8 @@ void PipelineManagerVulkan::SetLineWidth(float lineWidth) { // Wipe all line-drawing pipelines. pipelines_.Iterate([&](const VulkanPipelineKey &key, VulkanPipeline *value) { if (value->UsesLines()) { - vulkan_->Delete().QueueDeletePipeline(value->pipeline); + if (value->pipeline) + vulkan_->Delete().QueueDeletePipeline(value->pipeline); delete value; pipelines_.Remove(key); } diff --git a/ext/native/thin3d/VulkanRenderManager.h b/ext/native/thin3d/VulkanRenderManager.h index de4f192b01..1443aacc83 100644 --- a/ext/native/thin3d/VulkanRenderManager.h +++ b/ext/native/thin3d/VulkanRenderManager.h @@ -110,6 +110,7 @@ public: void BindPipeline(VkPipeline pipeline) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER); + _dbg_assert_(G3D, pipeline != VK_NULL_HANDLE); VkRenderData data{ VKRRenderCommand::BIND_PIPELINE }; data.pipeline.pipeline = pipeline; curRenderStep_->commands.push_back(data); From 24b9fb6ea90c9f6f1edc72c68c910d5ea80e51c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 19 Mar 2018 18:14:57 +0100 Subject: [PATCH 285/291] Buildfix --- GPU/Vulkan/PipelineManagerVulkan.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 15a06989d2..b28f36d8c5 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -213,7 +213,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip ERROR_LOG(G3D, "Failed creating graphics pipeline - bad shaders"); // Create a placeholder to avoid creating over and over if shader compiler broken. VulkanPipeline *nullPipeline = new VulkanPipeline(); - nullPipeline->pipeline = nullptr; + nullPipeline->pipeline = VK_NULL_HANDLE; nullPipeline->flags = 0; return nullPipeline; } @@ -285,7 +285,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip ERROR_LOG(G3D, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result)); // Create a placeholder to avoid creating over and over if something is broken. VulkanPipeline *nullPipeline = new VulkanPipeline(); - nullPipeline->pipeline = nullptr; + nullPipeline->pipeline = VK_NULL_HANDLE; nullPipeline->flags = 0; return nullPipeline; } From 78488a4ea66445dab26791139ea1515fb1e3d62c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 19 Mar 2018 19:38:42 +0100 Subject: [PATCH 286/291] Android: Restore auto screen orientation. Fixes #10708 This reverts commit 53a351c29de107f95a500dbe68adfac04a5decc1. --- UI/GameSettingsScreen.cpp | 4 ++-- android/src/org/ppsspp/ppsspp/NativeActivity.java | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 5b3e4a2705..1b67a4f462 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -656,8 +656,8 @@ void GameSettingsScreen::CreateViews() { #if PPSSPP_PLATFORM(ANDROID) if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { - static const char *screenRotation[] = {"Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed"}; - PopupMultiChoice *rot = systemSettings->Add(new PopupMultiChoice(&g_Config.iScreenRotation, co->T("Screen Rotation"), screenRotation, 1, ARRAY_SIZE(screenRotation), co->GetName(), screenManager())); + static const char *screenRotation[] = {"Auto", "Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed"}; + PopupMultiChoice *rot = systemSettings->Add(new PopupMultiChoice(&g_Config.iScreenRotation, co->T("Screen Rotation"), screenRotation, 0, ARRAY_SIZE(screenRotation), co->GetName(), screenManager())); rot->OnChoice.Handle(this, &GameSettingsScreen::OnScreenRotation); if (System_GetPropertyBool(SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE)) { diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 30b25854a2..854e7b62e5 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -373,8 +373,7 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C switch (rot) { case 0: - // Auto is no longer supported. - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); break; case 1: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); @@ -538,7 +537,7 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C int requestedOr = getRequestedOrientation(); boolean requestedPortrait = requestedOr == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || requestedOr == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; boolean detectedPortrait = pixelHeight > pixelWidth; - if (badOrientationCount < 3 && requestedPortrait != detectedPortrait) { + if (badOrientationCount < 3 && requestedPortrait != detectedPortrait && requestedOr != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { Log.e(TAG, "Bad orientation detected (w=" + pixelWidth + " h=" + pixelHeight + "! Recreating activity."); badOrientationCount++; recreate(); From 8f38c7949c9d2ee3cfa14eeb404cc2af894f8016 Mon Sep 17 00:00:00 2001 From: Florin9doi Date: Mon, 19 Mar 2018 23:05:23 +0200 Subject: [PATCH 287/291] Landscape Auto for Android --- UI/GameSettingsScreen.cpp | 2 +- android/src/org/ppsspp/ppsspp/NativeActivity.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 1b67a4f462..b27503e452 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -656,7 +656,7 @@ void GameSettingsScreen::CreateViews() { #if PPSSPP_PLATFORM(ANDROID) if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { - static const char *screenRotation[] = {"Auto", "Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed"}; + static const char *screenRotation[] = {"Auto", "Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed", "Landscape Auto"}; PopupMultiChoice *rot = systemSettings->Add(new PopupMultiChoice(&g_Config.iScreenRotation, co->T("Screen Rotation"), screenRotation, 0, ARRAY_SIZE(screenRotation), co->GetName(), screenManager())); rot->OnChoice.Handle(this, &GameSettingsScreen::OnScreenRotation); diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 854e7b62e5..96dadd6cf0 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -387,6 +387,9 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C case 4: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; + case 5: + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); + break; } } From f76e5e70a75bb756df9c31ff4a3076d5f98bf36d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 20 Mar 2018 12:02:57 +0100 Subject: [PATCH 288/291] Enable FlushInstructionCache on UWP, it's been allowed finally. Minor warning fixes, UWP buildfix Retarget UWP project to latest SDK. --- Common/Arm64Emitter.cpp | 2 -- Common/ArmEmitter.cpp | 2 -- Core/Config.cpp | 4 ++-- Core/FileSystems/BlobFileSystem.cpp | 2 +- Core/HW/StereoResampler.cpp | 1 + Core/MIPS/ARM/ArmJit.cpp | 10 --------- UWP/CommonUWP/CommonUWP.vcxproj | 4 ++-- UWP/CoreUWP/CoreUWP.vcxproj | 4 ++-- UWP/GPU_UWP/GPU_UWP.vcxproj | 4 ++-- UWP/NativeUWP/NativeUWP.vcxproj | 4 ++-- UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj | 4 ++-- UWP/UI_UWP/UI_UWP.vcxproj | 4 ++-- UWP/UWP.vcxproj | 24 ++++++++++----------- UWP/glslang_UWP/glslang_UWP.vcxproj | 8 ++++--- UWP/glslang_UWP/glslang_UWP.vcxproj.filters | 8 ++++++- UWP/libkirk_UWP/libkirk_UWP.vcxproj | 4 ++-- UWP/zlib_UWP/zlib_UWP.vcxproj | 4 ++-- 17 files changed, 44 insertions(+), 49 deletions(-) diff --git a/Common/Arm64Emitter.cpp b/Common/Arm64Emitter.cpp index abf9747601..3a18a308a2 100644 --- a/Common/Arm64Emitter.cpp +++ b/Common/Arm64Emitter.cpp @@ -327,9 +327,7 @@ void ARM64XEmitter::FlushIcacheSection(u8* start, u8* end) // Header file says this is equivalent to: sys_icache_invalidate(start, end - start); sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start); #elif PPSSPP_PLATFORM(WINDOWS) -#if !PPSSPP_PLATFORM(UWP) // Not available on UWP, which is very bad! FlushInstructionCache(GetCurrentProcess(), start, end - start); -#endif #elif PPSSPP_ARCH(ARM64) // Code from Dolphin, contributed by the Mono project. diff --git a/Common/ArmEmitter.cpp b/Common/ArmEmitter.cpp index 1321bf28be..8626cdc434 100644 --- a/Common/ArmEmitter.cpp +++ b/Common/ArmEmitter.cpp @@ -633,9 +633,7 @@ void ARMXEmitter::FlushIcacheSection(u8 *start, u8 *end) // Header file says this is equivalent to: sys_icache_invalidate(start, end - start); sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start); #elif PPSSPP_PLATFORM(WINDOWS) -#if !PPSSPP_PLATFORM(UWP) // Not available on UWP, which is very bad! FlushInstructionCache(GetCurrentProcess(), start, end - start); -#endif #elif PPSSPP_ARCH(ARM) #if defined(__clang__) || defined(__ANDROID__) diff --git a/Core/Config.cpp b/Core/Config.cpp index f89d75f738..cf38a3c788 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -713,8 +713,8 @@ static ConfigSetting controlSettings[] = { ConfigSetting("UseMouse", &g_Config.bMouseControl, false, true, true), ConfigSetting("MapMouse", &g_Config.bMapMouse, false, true, true), ConfigSetting("ConfineMap", &g_Config.bMouseConfine, false, true, true), - ConfigSetting("MouseSensitivity", &g_Config.fMouseSensitivity, 0.1, true, true), - ConfigSetting("MouseSmoothing", &g_Config.fMouseSmoothing, 0.9, true, true), + ConfigSetting("MouseSensitivity", &g_Config.fMouseSensitivity, 0.1f, true, true), + ConfigSetting("MouseSmoothing", &g_Config.fMouseSmoothing, 0.9f, true, true), ConfigSetting(false), }; diff --git a/Core/FileSystems/BlobFileSystem.cpp b/Core/FileSystems/BlobFileSystem.cpp index b0a7639b39..27b4113aa3 100644 --- a/Core/FileSystems/BlobFileSystem.cpp +++ b/Core/FileSystems/BlobFileSystem.cpp @@ -50,7 +50,7 @@ void BlobFileSystem::CloseFile(u32 handle) { size_t BlobFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) { auto entry = entries_.find(handle); if (entry != entries_.end()) { - s64 readSize = fileLoader_->ReadAt(entry->second, size, pointer); + s64 readSize = (s64)fileLoader_->ReadAt(entry->second, (size_t)size, pointer); entry->second += readSize; return (size_t)readSize; } diff --git a/Core/HW/StereoResampler.cpp b/Core/HW/StereoResampler.cpp index ca617d5b90..ee636a89fe 100644 --- a/Core/HW/StereoResampler.cpp +++ b/Core/HW/StereoResampler.cpp @@ -78,6 +78,7 @@ StereoResampler::StereoResampler() StereoResampler::~StereoResampler() { delete[] m_buffer; + m_buffer = nullptr; } void StereoResampler::UpdateBufferSize() { diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index 050cef8025..5ded4af630 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -179,20 +179,10 @@ void ArmJit::CompileDelaySlot(int flags) _MSR(true, false, R8); // Restore flags register } - void ArmJit::Compile(u32 em_address) { PROFILE_THIS_SCOPE("jitc"); -#if PPSSPP_PLATFORM(UWP) // INFO_LOG(JIT, "Compiling at %08x", em_address); - // Unfortunately Microsoft forgot to expose FlushInstructionCache to UWP applications... even though they expose - // the ability to generate code :( This works great on x86 but on ARM we're out of luck. - // This seems to be enough to flush the instruction cache: - // If this OutputDebugStringUTF8 is not called, we crash. - // But it only helps if the debugger is attached :( If not, we still crash. - // So really, the JIT is broken on Windows UWP ARM. - OutputDebugStringUTF8("JITHACK"); -#endif if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) { ClearCache(); diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index 828b6b150d..ac94b54c2e 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -46,9 +46,9 @@ 14.0 true Windows Store - 10.0.10240.0 + 10.0.14393.0 10.0 - 10.0.15063.0 + 10.0.16299.0 diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index b4e4bb6ea9..2211777fa4 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -46,9 +46,9 @@ 14.0 true Windows Store - 10.0.10240.0 + 10.0.14393.0 10.0 - 10.0.15063.0 + 10.0.16299.0 diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index 838205b571..0d1bc445ea 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -46,9 +46,9 @@ 14.0 true Windows Store - 10.0.10240.0 + 10.0.14393.0 10.0 - 10.0.15063.0 + 10.0.16299.0 diff --git a/UWP/NativeUWP/NativeUWP.vcxproj b/UWP/NativeUWP/NativeUWP.vcxproj index 599d491e0c..e6e8d6a89f 100644 --- a/UWP/NativeUWP/NativeUWP.vcxproj +++ b/UWP/NativeUWP/NativeUWP.vcxproj @@ -46,9 +46,9 @@ 14.0 true Windows Store - 10.0.10240.0 + 10.0.14393.0 10.0 - 10.0.15063.0 + 10.0.16299.0 diff --git a/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj b/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj index d36a6fec45..8e4ac9dfc2 100644 --- a/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj +++ b/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj @@ -46,9 +46,9 @@ 14.0 true Windows Store - 10.0.10240.0 + 10.0.14393.0 10.0 - 10.0.15063.0 + 10.0.16299.0 diff --git a/UWP/UI_UWP/UI_UWP.vcxproj b/UWP/UI_UWP/UI_UWP.vcxproj index 377dff98d5..7fda5b55f9 100644 --- a/UWP/UI_UWP/UI_UWP.vcxproj +++ b/UWP/UI_UWP/UI_UWP.vcxproj @@ -46,9 +46,9 @@ 14.0 true Windows Store - 10.0.10240.0 + 10.0.14393.0 10.0 - 10.0.15063.0 + 10.0.16299.0 diff --git a/UWP/UWP.vcxproj b/UWP/UWP.vcxproj index 16f370ea04..4f6ef42475 100644 --- a/UWP/UWP.vcxproj +++ b/UWP/UWP.vcxproj @@ -46,10 +46,10 @@ 14.0 true Windows Store - 10.0.10240.0 + 10.0.14393.0 10.0 PPSSPP_UWP - 10.0.15063.0 + 10.0.16299.0 @@ -117,39 +117,39 @@ - + - + - + - + - + - + - + - + - + @@ -490,7 +490,7 @@ copy AssetsGold\*.* Assets /Y - + diff --git a/UWP/glslang_UWP/glslang_UWP.vcxproj b/UWP/glslang_UWP/glslang_UWP.vcxproj index a4b35f9bcd..841a94fd24 100644 --- a/UWP/glslang_UWP/glslang_UWP.vcxproj +++ b/UWP/glslang_UWP/glslang_UWP.vcxproj @@ -46,9 +46,9 @@ 14.0 true Windows Store - 10.0.10240.0 + 10.0.14393.0 10.0 - 10.0.15063.0 + 10.0.16299.0 @@ -302,6 +302,7 @@ + @@ -347,6 +348,7 @@ + @@ -403,4 +405,4 @@ - + \ No newline at end of file diff --git a/UWP/glslang_UWP/glslang_UWP.vcxproj.filters b/UWP/glslang_UWP/glslang_UWP.vcxproj.filters index 443bf3bd7d..9d3fc6da3c 100644 --- a/UWP/glslang_UWP/glslang_UWP.vcxproj.filters +++ b/UWP/glslang_UWP/glslang_UWP.vcxproj.filters @@ -160,6 +160,9 @@ OGLCompilersDLL + + glslang\MachineIndependent + @@ -317,5 +320,8 @@ OGLCompilersDLL + + glslang\MachineIndependent + - + \ No newline at end of file diff --git a/UWP/libkirk_UWP/libkirk_UWP.vcxproj b/UWP/libkirk_UWP/libkirk_UWP.vcxproj index 49ecaec065..d993e1145e 100644 --- a/UWP/libkirk_UWP/libkirk_UWP.vcxproj +++ b/UWP/libkirk_UWP/libkirk_UWP.vcxproj @@ -46,9 +46,9 @@ 14.0 true Windows Store - 10.0.10240.0 + 10.0.14393.0 10.0 - 10.0.15063.0 + 10.0.16299.0 diff --git a/UWP/zlib_UWP/zlib_UWP.vcxproj b/UWP/zlib_UWP/zlib_UWP.vcxproj index ce7b30285c..347bd1ea74 100644 --- a/UWP/zlib_UWP/zlib_UWP.vcxproj +++ b/UWP/zlib_UWP/zlib_UWP.vcxproj @@ -46,9 +46,9 @@ 14.0 true Windows Store - 10.0.10240.0 + 10.0.14393.0 10.0 - 10.0.15063.0 + 10.0.16299.0 From 9c68e2c410f5ec91be35d31ee157501001612087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 21 Mar 2018 08:50:02 +0100 Subject: [PATCH 289/291] Revert "Update glslang to the latest version" to fix #10748 Should take a real look sometime. This reverts commit d4a4844bff8cf763af940c2e5a2eff715ec352de. --- ext/glslang | 2 +- ext/glslang-build/Android.mk | 1 - ext/glslang.vcxproj | 2 -- ext/glslang.vcxproj.filters | 6 ------ 4 files changed, 1 insertion(+), 10 deletions(-) diff --git a/ext/glslang b/ext/glslang index 0af69da12e..2edde6665d 160000 --- a/ext/glslang +++ b/ext/glslang @@ -1 +1 @@ -Subproject commit 0af69da12ede4ce588b7316be55fb095dfe2fb7d +Subproject commit 2edde6665d9a56ead5ea0e55b4e64d9a803e6164 diff --git a/ext/glslang-build/Android.mk b/ext/glslang-build/Android.mk index 47e232c5cf..8bf8106ca0 100644 --- a/ext/glslang-build/Android.mk +++ b/ext/glslang-build/Android.mk @@ -9,7 +9,6 @@ LOCAL_ARM_MODE := arm LOCAL_SRC_FILES := \ ../glslang/glslang/GenericCodeGen/CodeGen.cpp \ ../glslang/glslang/GenericCodeGen/Link.cpp \ - ../glslang/glslang/MachineIndependent/attribute.cpp \ ../glslang/glslang/MachineIndependent/Constant.cpp \ ../glslang/glslang/MachineIndependent/glslang_tab.cpp \ ../glslang/glslang/MachineIndependent/InfoSink.cpp \ diff --git a/ext/glslang.vcxproj b/ext/glslang.vcxproj index 3711148daa..54b3581255 100644 --- a/ext/glslang.vcxproj +++ b/ext/glslang.vcxproj @@ -152,7 +152,6 @@ - @@ -208,7 +207,6 @@ - diff --git a/ext/glslang.vcxproj.filters b/ext/glslang.vcxproj.filters index d37c8c805e..af94d50565 100644 --- a/ext/glslang.vcxproj.filters +++ b/ext/glslang.vcxproj.filters @@ -137,9 +137,6 @@ HLSL - - glslang - @@ -293,9 +290,6 @@ HLSL - - glslang - From fb798cf6b2c086b7bee0790cb71416dda4f72026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 23 Mar 2018 10:26:33 +0100 Subject: [PATCH 290/291] Win32 textdrawer: Fix rare crash affecting Patapon 2 in savedata manager. See 10764. --- Common/Vulkan/VulkanContext.h | 3 --- Core/FileSystems/DirectoryFileSystem.cpp | 4 ++-- ext/native/gfx_es2/draw_text_win.cpp | 6 ++++++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index ac4d98148f..6466f7b390 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -8,9 +8,6 @@ #include "base/logging.h" #include "Common/Vulkan/VulkanLoader.h" -// Amount of time, in nanoseconds, to wait for a command buffer to complete -#define FENCE_TIMEOUT 10000000000 - enum { VULKAN_FLAG_VALIDATE = 1, VULKAN_FLAG_PRESENT_MAILBOX = 2, diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 6e53be5110..f4db57f7ab 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -186,7 +186,7 @@ bool DirectoryFileHandle::Open(std::string &basePath, std::string &fileName, Fil #endif std::string fullName = GetLocalPath(basePath,fileName); - DEBUG_LOG(FILESYS,"Actually opening %s", fullName.c_str()); + VERBOSE_LOG(FILESYS,"Actually opening %s", fullName.c_str()); // On the PSP, truncating doesn't lose data. If you seek later, you'll recover it. // This is abnormal, so we deviate from the PSP's behavior and truncate on write/close. @@ -1002,7 +1002,7 @@ u32 VFSFileSystem::OpenFile(std::string filename, FileAccess access, const char std::string fullName = GetLocalPath(filename); const char *fullNameC = fullName.c_str(); - DEBUG_LOG(FILESYS,"VFSFileSystem actually opening %s (%s)", fullNameC, filename.c_str()); + VERBOSE_LOG(FILESYS,"VFSFileSystem actually opening %s (%s)", fullNameC, filename.c_str()); size_t size; u8 *data = VFSReadFile(fullNameC, &size); diff --git a/ext/native/gfx_es2/draw_text_win.cpp b/ext/native/gfx_es2/draw_text_win.cpp index 0476bd564e..1cae07f795 100644 --- a/ext/native/gfx_es2/draw_text_win.cpp +++ b/ext/native/gfx_es2/draw_text_win.cpp @@ -231,6 +231,12 @@ void TextDrawerWin32::DrawString(DrawBuffer &target, const char *str, float x, f size.cx = MAX_TEXT_WIDTH; if (size.cy > MAX_TEXT_HEIGHT) size.cy = MAX_TEXT_HEIGHT; + // Prevent zero-sized textures, which can occur. Not worth to avoid + // creating the texture altogether in this case. + if (size.cx == 0) + size.cx = 1; + if (size.cy == 0) + size.cy = 1; entry = new TextStringEntry(); entry->width = size.cx; From 7761d2366b1622726ed666957085daf7573cff70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 23 Mar 2018 10:48:54 +0100 Subject: [PATCH 291/291] Android: Prevent a text bitmap size from becoming 0 on '\r\n'. Fixes #10764 (unless there are more platforms where it's broken...) --- .../src/org/ppsspp/ppsspp/TextRenderer.java | 22 ++++++++++++++----- ext/native/gfx_es2/draw_text_android.cpp | 9 ++++++-- ext/native/gfx_es2/draw_text_win.cpp | 3 ++- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/android/src/org/ppsspp/ppsspp/TextRenderer.java b/android/src/org/ppsspp/ppsspp/TextRenderer.java index 8c794a56a8..e2e4c37bef 100644 --- a/android/src/org/ppsspp/ppsspp/TextRenderer.java +++ b/android/src/org/ppsspp/ppsspp/TextRenderer.java @@ -26,12 +26,17 @@ public class TextRenderer { } } private static Point measureLine(String string, double textSize) { - p.setTextSize((float)textSize); - int w = (int)p.measureText(string); + int w; + if (string.length() > 0) { + p.setTextSize((float)textSize); + w = (int)p.measureText(string); + // Round width up to even already here to avoid annoyances from odd-width 16-bit textures which + // OpenGL does not like - each line must be 4-byte aligned + w = (w + 5) & ~1; + } else { + w = 1; + } int h = (int)(p.descent() - p.ascent() + 2.0f); - // Round width up to even already here to avoid annoyances from odd-width 16-bit textures which - // OpenGL does not like - each line must be 4-byte aligned - w = (w + 5) & ~1; Point p = new Point(); p.x = w; p.y = h; @@ -57,6 +62,10 @@ public class TextRenderer { int w = s.x; int h = s.y; + if (w == 0) + w = 1; + if (h == 0) + h = 1; Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bmp); @@ -65,7 +74,8 @@ public class TextRenderer { String lines[] = string.replaceAll("\\r", "").split("\n"); float y = 1.0f; for (String line : lines) { - canvas.drawText(line, 1, -p.ascent() + y, p); + if (line.length() > 0) + canvas.drawText(line, 1, -p.ascent() + y, p); y += p.descent() - p.ascent(); } diff --git a/ext/native/gfx_es2/draw_text_android.cpp b/ext/native/gfx_es2/draw_text_android.cpp index 1bc3bc6639..f80994edd2 100644 --- a/ext/native/gfx_es2/draw_text_android.cpp +++ b/ext/native/gfx_es2/draw_text_android.cpp @@ -184,8 +184,13 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, jstring jstr = env_->NewStringUTF(text.c_str()); uint32_t textSize = env_->CallStaticIntMethod(cls_textRenderer, method_measureText, jstr, size); - int imageWidth = (textSize >> 16); - int imageHeight = (textSize & 0xFFFF); + int imageWidth = (short)(textSize >> 16); + int imageHeight = (short)(textSize & 0xFFFF); + if (imageWidth <= 0) + imageWidth = 1; + if (imageHeight <= 0) + imageHeight = 1; + jintArray imageData = (jintArray)env_->CallStaticObjectMethod(cls_textRenderer, method_renderText, jstr, size); env_->DeleteLocalRef(jstr); diff --git a/ext/native/gfx_es2/draw_text_win.cpp b/ext/native/gfx_es2/draw_text_win.cpp index 1cae07f795..5bc066f297 100644 --- a/ext/native/gfx_es2/draw_text_win.cpp +++ b/ext/native/gfx_es2/draw_text_win.cpp @@ -232,7 +232,8 @@ void TextDrawerWin32::DrawString(DrawBuffer &target, const char *str, float x, f if (size.cy > MAX_TEXT_HEIGHT) size.cy = MAX_TEXT_HEIGHT; // Prevent zero-sized textures, which can occur. Not worth to avoid - // creating the texture altogether in this case. + // creating the texture altogether in this case. One example is a string + // containing only '\r\n', see issue #10764. if (size.cx == 0) size.cx = 1; if (size.cy == 0)