From 1ed7f0d7fde10e6e772cdc1240f9f7b60db75c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Dec 2016 13:22:48 +0100 Subject: [PATCH] More modern way to specify vertex data format (inputlayout) --- GPU/Software/SoftGpu.cpp | 16 +++- Windows/GPU/WindowsVulkanContext.cpp | 3 +- ext/native/gfx_es2/draw_buffer.cpp | 18 ++-- ext/native/thin3d/thin3d.h | 29 +++--- ext/native/thin3d/thin3d_d3d9.cpp | 54 ++++++----- ext/native/thin3d/thin3d_gl.cpp | 57 ++++++------ ext/native/thin3d/thin3d_vulkan.cpp | 132 +++++++++++++++++---------- 7 files changed, 181 insertions(+), 128 deletions(-) diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 25c5a1af2a..80236f84c1 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -57,13 +57,19 @@ SoftGPU::SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *_thin3D) using namespace Draw; fbTex = thin3d->CreateTexture(LINEAR2D, DataFormat::R8G8B8A8_UNORM, 480, 272, 1, 1); - std::vector components; - components.push_back(VertexComponent("Position", SEM_POSITION, DataFormat::R32G32B32_FLOAT, 0)); - components.push_back(VertexComponent("TexCoord0", SEM_TEXCOORD0, DataFormat::R32G32_FLOAT, 12)); - components.push_back(VertexComponent("Color0", SEM_COLOR0, DataFormat::R8G8B8A8_UNORM, 20)); + InputLayoutDesc desc = { + { + { 24, false }, + }, + { + { 0, SEM_POSITION, DataFormat::R32G32B32_FLOAT, 0 }, + { 0, SEM_TEXCOORD0, DataFormat::R32G32_FLOAT, 12 }, + { 0, SEM_COLOR0, DataFormat::R32G32B32_FLOAT, 20 }, + }, + }; ShaderModule *vshader = thin3d->GetVshaderPreset(VS_TEXTURE_COLOR_2D); - vformat = thin3d->CreateVertexFormat(components, 24, vshader); + vformat = thin3d->CreateInputLayout(desc); vdata = thin3d->CreateBuffer(24 * 4, BufferUsageFlag::DYNAMIC | BufferUsageFlag::VERTEXDATA); idata = thin3d->CreateBuffer(sizeof(int) * 6, BufferUsageFlag::DYNAMIC | BufferUsageFlag::INDEXDATA); diff --git a/Windows/GPU/WindowsVulkanContext.cpp b/Windows/GPU/WindowsVulkanContext.cpp index 6cdfe217dd..f9562c4dcf 100644 --- a/Windows/GPU/WindowsVulkanContext.cpp +++ b/Windows/GPU/WindowsVulkanContext.cpp @@ -140,7 +140,8 @@ static VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, VkDebugRep return false; #ifdef _WIN32 - OutputDebugStringA(message.str().c_str()); + std::string msg = message.str(); + OutputDebugStringA(msg.c_str()); if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { if (options->breakOnError) { DebugBreak(); diff --git a/ext/native/gfx_es2/draw_buffer.cpp b/ext/native/gfx_es2/draw_buffer.cpp index 6bb276e616..0045f01fba 100644 --- a/ext/native/gfx_es2/draw_buffer.cpp +++ b/ext/native/gfx_es2/draw_buffer.cpp @@ -41,14 +41,18 @@ void DrawBuffer::Init(Draw::DrawContext *t3d) { t3d_ = t3d; inited_ = true; - std::vector components; - components.push_back(VertexComponent("Position", SEM_POSITION, DataFormat::R32G32B32_FLOAT, 0)); - components.push_back(VertexComponent("TexCoord0", SEM_TEXCOORD0, DataFormat::R32G32_FLOAT, 12)); - components.push_back(VertexComponent("Color0", SEM_COLOR0, DataFormat::R8G8B8A8_UNORM, 20)); + InputLayoutDesc desc = { + { + {sizeof(Vertex), false}, + }, + { + { 0, SEM_POSITION, DataFormat::R32G32B32_FLOAT, 0 }, + { 0, SEM_TEXCOORD0, DataFormat::R32G32_FLOAT, 12 }, + { 0, SEM_COLOR0, DataFormat::R8G8B8A8_UNORM, 20 }, + }, + }; - ShaderModule *vshader = t3d_->GetVshaderPreset(VS_TEXTURE_COLOR_2D); - - vformat_ = t3d_->CreateVertexFormat(components, 24, vshader); + vformat_ = t3d_->CreateInputLayout(desc); if (vformat_->RequiresBuffer()) { vbuf_ = t3d_->CreateBuffer(MAX_VERTS * sizeof(Vertex), BufferUsageFlag::DYNAMIC | BufferUsageFlag::VERTEXDATA); } else { diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index ab8279f836..676684633f 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -299,18 +299,21 @@ protected: int width_, height_, depth_; }; -struct VertexComponent { - VertexComponent() : name(nullptr), type(DataFormat::UNDEFINED), semantic(255), offset(255) {} - VertexComponent(const char *name, Semantic semantic, DataFormat dataType, uint8_t offset) { - this->name = name; - this->semantic = semantic; - this->type = dataType; - this->offset = offset; - } - const char *name; - uint8_t semantic; - DataFormat type; - uint8_t offset; +struct BindingDesc { + int stride; + bool instanceRate; +}; + +struct AttributeDesc { + int binding; + int location; // corresponds to semantic + DataFormat format; + int offset; +}; + +struct InputLayoutDesc { + std::vector bindings; + std::vector attributes; }; class InputLayout : public RefCountedObject { @@ -451,7 +454,7 @@ public: virtual RasterState *CreateRasterState(const RasterStateDesc &desc) = 0; virtual Buffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0; virtual Pipeline *CreatePipeline(const PipelineDesc &desc) = 0; - virtual InputLayout *CreateVertexFormat(const std::vector &components, int stride, ShaderModule *vshader) = 0; + virtual InputLayout *CreateInputLayout(const InputLayoutDesc &desc) = 0; virtual Texture *CreateTexture() = 0; // To be later filled in by ->LoadFromFile or similar. virtual Texture *CreateTexture(TextureType type, DataFormat format, int width, int height, int depth, int mipLevels) = 0; diff --git a/ext/native/thin3d/thin3d_d3d9.cpp b/ext/native/thin3d/thin3d_d3d9.cpp index a603a2fb25..cfb8483855 100644 --- a/ext/native/thin3d/thin3d_d3d9.cpp +++ b/ext/native/thin3d/thin3d_d3d9.cpp @@ -96,7 +96,7 @@ static const int primCountDivisor[] = { 1, }; -class Thin3DDX9DepthStencilState : public DepthStencilState { +class D3D9DepthStencilState : public DepthStencilState { public: BOOL depthTestEnabled; BOOL depthWriteEnabled; @@ -230,24 +230,25 @@ private: }; -class Thin3DDX9VertexFormat : public InputLayout { +class D3D9InputLayout : public InputLayout { public: - Thin3DDX9VertexFormat(LPDIRECT3DDEVICE9 device, const std::vector &components, int stride); - ~Thin3DDX9VertexFormat() { + D3D9InputLayout(LPDIRECT3DDEVICE9 device, const InputLayoutDesc &desc); + ~D3D9InputLayout() { if (decl_) { decl_->Release(); } } - int GetStride() const { return stride_; } + int GetStride(int binding) const { return stride_[binding]; } void Apply(LPDIRECT3DDEVICE9 device) { device->SetVertexDeclaration(decl_); } bool RequiresBuffer() override { return false; } + private: LPDIRECT3DVERTEXDECLARATION9 decl_; - int stride_; + int stride_[4]; }; class D3D9ShaderModule : public ShaderModule { @@ -460,7 +461,7 @@ public: RasterState *CreateRasterState(const RasterStateDesc &desc) override; Buffer *CreateBuffer(size_t size, uint32_t usageFlags) override; Pipeline *CreatePipeline(const PipelineDesc &desc) override; - InputLayout *CreateVertexFormat(const std::vector &components, int stride, ShaderModule *vshader) override; + InputLayout *CreateInputLayout(const InputLayoutDesc &desc) override; Texture *CreateTexture() override; Texture *CreateTexture(TextureType type, DataFormat format, int width, int height, int depth, int mipLevels) override; ShaderModule *CreateShaderModule(ShaderStage stage, const char *glsl_source, const char *hlsl_source, const char *vulkan_source) override; @@ -471,7 +472,7 @@ public: bs->Apply(device_); } void SetDepthStencilState(DepthStencilState *state) override { - Thin3DDX9DepthStencilState *bs = static_cast(state); + D3D9DepthStencilState *bs = static_cast(state); bs->Apply(device_); } void SetRasterState(RasterState *state) override { @@ -565,15 +566,15 @@ Pipeline *D3D9Context::CreatePipeline(const PipelineDesc &desc) { } DepthStencilState *D3D9Context::CreateDepthStencilState(const DepthStencilStateDesc &desc) { - Thin3DDX9DepthStencilState *ds = new Thin3DDX9DepthStencilState(); + D3D9DepthStencilState *ds = new D3D9DepthStencilState(); ds->depthTestEnabled = desc.depthTestEnabled; ds->depthWriteEnabled = desc.depthWriteEnabled; ds->depthCompare = compareToD3D9[(int)desc.depthCompare]; return ds; } -InputLayout *D3D9Context::CreateVertexFormat(const std::vector &components, int stride, ShaderModule *vshader) { - Thin3DDX9VertexFormat *fmt = new Thin3DDX9VertexFormat(device_, components, stride); +InputLayout *D3D9Context::CreateInputLayout(const InputLayoutDesc &desc) { + D3D9InputLayout *fmt = new D3D9InputLayout(device_, desc); return fmt; } @@ -676,26 +677,29 @@ static int VertexDataTypeToD3DType(DataFormat type) { } } -Thin3DDX9VertexFormat::Thin3DDX9VertexFormat(LPDIRECT3DDEVICE9 device, const std::vector &components, int stride) : decl_(NULL) { - D3DVERTEXELEMENT9 *elements = new D3DVERTEXELEMENT9[components.size() + 1]; +D3D9InputLayout::D3D9InputLayout(LPDIRECT3DDEVICE9 device, const InputLayoutDesc &desc) : decl_(NULL) { + D3DVERTEXELEMENT9 *elements = new D3DVERTEXELEMENT9[desc.attributes.size() + 1]; size_t i; - for (i = 0; i < components.size(); i++) { - elements[i].Stream = 0; - elements[i].Offset = components[i].offset; + for (i = 0; i < desc.attributes.size(); i++) { + elements[i].Stream = desc.attributes[i].binding; + elements[i].Offset = desc.attributes[i].offset; elements[i].Method = D3DDECLMETHOD_DEFAULT; - SemanticToD3D9UsageAndIndex(components[i].semantic, &elements[i].Usage, &elements[i].UsageIndex); - elements[i].Type = VertexDataTypeToD3DType(components[i].type); + SemanticToD3D9UsageAndIndex(desc.attributes[i].location, &elements[i].Usage, &elements[i].UsageIndex); + elements[i].Type = VertexDataTypeToD3DType(desc.attributes[i].format); } D3DVERTEXELEMENT9 end = D3DDECL_END(); // Zero the last one. memcpy(&elements[i], &end, sizeof(elements[i])); + for (i = 0; i < desc.bindings.size(); i++) { + stride_[i] = desc.bindings[i].stride; + } + HRESULT hr = device->CreateVertexDeclaration(elements, &decl_); if (FAILED(hr)) { ELOG("Error creating vertex decl"); } delete[] elements; - stride_ = stride; } Buffer *D3D9Context::CreateBuffer(size_t size, uint32_t usageFlags) { @@ -709,9 +713,9 @@ void D3D9Pipeline::Apply(LPDIRECT3DDEVICE9 device) { void D3D9Context::Draw(Primitive prim, InputLayout *format, Buffer *vdata, int vertexCount, int offset) { Thin3DDX9Buffer *vbuf = static_cast(vdata); - Thin3DDX9VertexFormat *fmt = static_cast(format); + D3D9InputLayout *fmt = static_cast(format); - vbuf->BindAsVertexBuf(device_, fmt->GetStride(), offset); + vbuf->BindAsVertexBuf(device_, fmt->GetStride(9), offset); curPipeline_->Apply(device_); fmt->Apply(device_); device_->DrawPrimitive(primToD3D9[(int)prim], offset, vertexCount / 3); @@ -720,21 +724,21 @@ void D3D9Context::Draw(Primitive prim, InputLayout *format, Buffer *vdata, int v void D3D9Context::DrawIndexed(Primitive prim, InputLayout *format, Buffer *vdata, Buffer *idata, int vertexCount, int offset) { Thin3DDX9Buffer *vbuf = static_cast(vdata); Thin3DDX9Buffer *ibuf = static_cast(idata); - Thin3DDX9VertexFormat *fmt = static_cast(format); + D3D9InputLayout *fmt = static_cast(format); curPipeline_->Apply(device_); fmt->Apply(device_); - vbuf->BindAsVertexBuf(device_, fmt->GetStride(), offset); + vbuf->BindAsVertexBuf(device_, fmt->GetStride(0), offset); ibuf->BindAsIndexBuf(device_); device_->DrawIndexedPrimitive(primToD3D9[(int)prim], 0, 0, vertexCount, 0, vertexCount / primCountDivisor[(int)prim]); } void D3D9Context::DrawUP(Primitive prim, InputLayout *format, const void *vdata, int vertexCount) { - Thin3DDX9VertexFormat *fmt = static_cast(format); + D3D9InputLayout *fmt = static_cast(format); curPipeline_->Apply(device_); fmt->Apply(device_); - device_->DrawPrimitiveUP(primToD3D9[(int)prim], vertexCount / 3, vdata, fmt->GetStride()); + device_->DrawPrimitiveUP(primToD3D9[(int)prim], vertexCount / 3, vdata, fmt->GetStride(0)); } static uint32_t SwapRB(uint32_t c) { diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 74a1217855..91551d1a75 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -330,9 +330,9 @@ bool OpenGLShaderModule::Compile(const char *source) { return ok_; } -class OpenGLVertexFormat : public InputLayout, GfxResourceHolder { +class OpenGLInputLayout : public InputLayout, GfxResourceHolder { public: - ~OpenGLVertexFormat(); + ~OpenGLInputLayout(); void Apply(const void *base = nullptr); void Unapply(); @@ -343,7 +343,8 @@ public: return id_ != 0; } - std::vector components_; + InputLayoutDesc desc; + int semanticsMask_; // Fast way to check what semantics to enable/disable. int stride_; GLuint id_; @@ -411,7 +412,7 @@ public: RasterState *CreateRasterState(const RasterStateDesc &desc) override; Buffer *CreateBuffer(size_t size, uint32_t usageFlags) override; Pipeline *CreatePipeline(const PipelineDesc &desc) override; - InputLayout *CreateVertexFormat(const std::vector &components, int stride, ShaderModule *vshader) override; + InputLayout *CreateInputLayout(const InputLayoutDesc &desc) override; Texture *CreateTexture(TextureType type, DataFormat format, int width, int height, int depth, int mipLevels) override; Texture *CreateTexture() override; @@ -529,10 +530,9 @@ OpenGLContext::~OpenGLContext() { samplerStates_.clear(); } -InputLayout *OpenGLContext::CreateVertexFormat(const std::vector &components, int stride, ShaderModule *vshader) { - OpenGLVertexFormat *fmt = new OpenGLVertexFormat(); - fmt->components_ = components; - fmt->stride_ = stride; +InputLayout *OpenGLContext::CreateInputLayout(const InputLayoutDesc &desc) { + OpenGLInputLayout *fmt = new OpenGLInputLayout(); + fmt->desc = desc; fmt->Compile(); return fmt; } @@ -705,18 +705,18 @@ void Thin3DGLTexture::Finalize(int zim_flags) { } -OpenGLVertexFormat::~OpenGLVertexFormat() { +OpenGLInputLayout::~OpenGLInputLayout() { if (id_) { glDeleteVertexArrays(1, &id_); } } -void OpenGLVertexFormat::Compile() { - int sem = 0; - for (int i = 0; i < (int)components_.size(); i++) { - sem |= 1 << components_[i].semantic; + +void OpenGLInputLayout::Compile() { + int semMask = 0; + for (int i = 0; i < (int)desc.attributes.size(); i++) { + semMask |= 1 << desc.attributes[i].location; } - semanticsMask_ = sem; - // TODO : Compute stride as well? + semanticsMask_ = semMask; if (gl_extensions.ARB_vertex_array_object && gl_extensions.IsCoreContext) { glGenVertexArrays(1, &id_); @@ -727,11 +727,11 @@ void OpenGLVertexFormat::Compile() { lastBase_ = -1; } -void OpenGLVertexFormat::GLLost() { +void OpenGLInputLayout::GLLost() { id_ = 0; } -void OpenGLVertexFormat::GLRestore() { +void OpenGLInputLayout::GLRestore() { Compile(); } @@ -938,7 +938,7 @@ void OpenGLPipeline::Unapply() { void OpenGLContext::Draw(Primitive prim, InputLayout *format, Buffer *vdata, int vertexCount, int offset) { OpenGLBuffer *vbuf = static_cast(vdata); - OpenGLVertexFormat *fmt = static_cast(format); + OpenGLInputLayout *fmt = static_cast(format); vbuf->Bind(); fmt->Apply(); @@ -953,7 +953,7 @@ void OpenGLContext::Draw(Primitive prim, InputLayout *format, Buffer *vdata, int void OpenGLContext::DrawIndexed(Primitive prim, InputLayout *format, Buffer *vdata, Buffer *idata, int vertexCount, int offset) { OpenGLBuffer *vbuf = static_cast(vdata); OpenGLBuffer *ibuf = static_cast(idata); - OpenGLVertexFormat *fmt = static_cast(format); + OpenGLInputLayout *fmt = static_cast(format); vbuf->Bind(); fmt->Apply(); @@ -968,7 +968,7 @@ void OpenGLContext::DrawIndexed(Primitive prim, InputLayout *format, Buffer *vda } void OpenGLContext::DrawUP(Primitive prim, InputLayout *format, const void *vdata, int vertexCount) { - OpenGLVertexFormat *fmt = static_cast(format); + OpenGLInputLayout *fmt = static_cast(format); fmt->Apply(vdata); curPipeline_->Apply(); @@ -1008,7 +1008,7 @@ DrawContext *T3DCreateGLContext() { return new OpenGLContext(); } -void OpenGLVertexFormat::Apply(const void *base) { +void OpenGLInputLayout::Apply(const void *base) { if (id_ != 0) { glBindVertexArray(id_); } @@ -1026,19 +1026,20 @@ void OpenGLVertexFormat::Apply(const void *base) { intptr_t b = (intptr_t)base; if (b != lastBase_) { - for (size_t i = 0; i < components_.size(); i++) { - switch (components_[i].type) { + for (size_t i = 0; i < desc.attributes.size(); i++) { + size_t stride = desc.bindings[desc.attributes[i].binding].stride; + switch (desc.attributes[i].format) { case DataFormat::R32G32_FLOAT: - glVertexAttribPointer(components_[i].semantic, 2, GL_FLOAT, GL_FALSE, stride_, (void *)(b + (intptr_t)components_[i].offset)); + 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(components_[i].semantic, 3, GL_FLOAT, GL_FALSE, stride_, (void *)(b + (intptr_t)components_[i].offset)); + 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(components_[i].semantic, 4, GL_FLOAT, GL_FALSE, stride_, (void *)(b + (intptr_t)components_[i].offset)); + 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(components_[i].semantic, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride_, (void *)(b + (intptr_t)components_[i].offset)); + 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: @@ -1052,7 +1053,7 @@ void OpenGLVertexFormat::Apply(const void *base) { } } -void OpenGLVertexFormat::Unapply() { +void OpenGLInputLayout::Unapply() { if (id_ == 0) { for (int i = 0; i < (int)SEM_MAX; i++) { if (semanticsMask_ & (1 << i)) { diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 99f70c34ea..52886c0b62 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -297,34 +297,15 @@ inline VkFormat ConvertVertexDataTypeToVk(DataFormat type) { } } -class VKVertexFormat : public InputLayout { +class VKInputLayout : public InputLayout { public: - void ToVulkan(VkPipelineVertexInputStateCreateInfo *info, VkVertexInputAttributeDescription *attrDescs, VkVertexInputBindingDescription *bindDescs) { - memset(info, 0, sizeof(*info)); - info->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - for (uint32_t i = 0; i < components_.size(); i++) { - attrDescs[i].binding = 0; - attrDescs[i].format = ConvertVertexDataTypeToVk(components_[i].type); - attrDescs[i].location = (int)components_[i].semantic; - attrDescs[i].offset = components_[i].offset; - } - bindDescs[0].binding = 0; - bindDescs[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - bindDescs[0].stride = stride_; - - info->vertexAttributeDescriptionCount = (uint32_t)components_.size(); - info->pVertexAttributeDescriptions = attrDescs; - info->vertexBindingDescriptionCount = 1; - info->pVertexBindingDescriptions = bindDescs; - info->flags = 0; - } - bool RequiresBuffer() { return false; } - std::vector components_; - int stride_; + std::vector bindings; + std::vector attributes; + VkPipelineVertexInputStateCreateInfo visc; }; class VKPipeline : public Pipeline { @@ -409,7 +390,7 @@ public: DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) override; BlendState *CreateBlendState(const BlendStateDesc &desc) override; Buffer *CreateBuffer(size_t size, uint32_t usageFlags) override; - InputLayout *CreateVertexFormat(const std::vector &components, int stride, ShaderModule *vshader) override; + InputLayout *CreateInputLayout(const InputLayoutDesc &desc) override; SamplerState *CreateSamplerState(const SamplerStateDesc &desc) override; RasterState *CreateRasterState(const RasterStateDesc &desc) override; Pipeline *CreatePipeline(const PipelineDesc &desc) override; @@ -490,7 +471,7 @@ private: VKDepthStencilState *curDepthStencilState_; VKPipeline *curPipeline_; VkPrimitiveTopology curPrim_; - VKVertexFormat *curVertexFormat_; + VKInputLayout *curInputLayout_; VKRasterState *curRasterState_; // We keep a pipeline state cache. @@ -532,13 +513,54 @@ private: VulkanPushBuffer *push_; }; -VkFormat FormatToVulkan(DataFormat fmt, int *bpp) { - switch (fmt) { - case DataFormat::R8G8B8A8_UNORM: *bpp = 32; return VK_FORMAT_R8G8B8A8_UNORM; - case DataFormat::R4G4B4A4_UNORM: *bpp = 16; return VK_FORMAT_R4G4B4A4_UNORM_PACK16; - case DataFormat::D24_S8: *bpp = 32; return VK_FORMAT_D24_UNORM_S8_UINT; - case DataFormat::D16: *bpp = 16; return VK_FORMAT_D16_UNORM; - default: return VK_FORMAT_UNDEFINED; +int GetBpp(VkFormat format) { + switch (format) { + case VK_FORMAT_R8G8B8A8_UNORM: + return 32; + case VK_FORMAT_R4G4B4A4_UNORM_PACK16: + return 16; + case VK_FORMAT_D24_UNORM_S8_UINT: + return 32; + case VK_FORMAT_D16_UNORM: + return 16; + default: + return 0; + } +} + +VkFormat DataFormatToVulkan(DataFormat format) { + switch (format) { + case DataFormat::D16: return VK_FORMAT_D16_UNORM; + case DataFormat::D32F: return VK_FORMAT_D32_SFLOAT; + case DataFormat::D32F_S8: return VK_FORMAT_D32_SFLOAT_S8_UINT; + case DataFormat::S8: return VK_FORMAT_S8_UINT; + case DataFormat::R16_FLOAT: return VK_FORMAT_R16_SFLOAT; + case DataFormat::R16G16_FLOAT: return VK_FORMAT_R16G16_SFLOAT; + case DataFormat::R16G16B16A16_FLOAT: return VK_FORMAT_R16G16B16A16_SFLOAT; + case DataFormat::R8_UNORM: return VK_FORMAT_R8_UNORM; + case DataFormat::R8G8_UNORM: return VK_FORMAT_R8G8_UNORM; + case DataFormat::R8G8B8_UNORM: return VK_FORMAT_R8G8B8_UNORM; + case DataFormat::R8G8B8A8_UNORM: return VK_FORMAT_R8G8B8A8_UNORM; + case DataFormat::R4G4_UNORM: return VK_FORMAT_R4G4_UNORM_PACK8; + case DataFormat::R4G4B4A4_UNORM: return VK_FORMAT_R4G4B4A4_UNORM_PACK16; + case DataFormat::R32_FLOAT: return VK_FORMAT_R32_SFLOAT; + case DataFormat::R32G32_FLOAT: return VK_FORMAT_R32G32_SFLOAT; + case DataFormat::R32G32B32_FLOAT: return VK_FORMAT_R32G32B32_SFLOAT; + case DataFormat::R32G32B32A32_FLOAT: return VK_FORMAT_R32G32B32A32_SFLOAT; + + case DataFormat::BC1_RGBA_UNORM_BLOCK: return VK_FORMAT_BC1_RGBA_UNORM_BLOCK; + case DataFormat::BC2_UNORM_BLOCK: return VK_FORMAT_BC2_UNORM_BLOCK; + case DataFormat::BC3_UNORM_BLOCK: return VK_FORMAT_BC3_UNORM_BLOCK; + case DataFormat::BC4_UNORM_BLOCK: return VK_FORMAT_BC4_UNORM_BLOCK; + case DataFormat::BC4_SNORM_BLOCK: return VK_FORMAT_BC4_SNORM_BLOCK; + case DataFormat::BC5_UNORM_BLOCK: return VK_FORMAT_BC5_UNORM_BLOCK; + case DataFormat::BC5_SNORM_BLOCK: return VK_FORMAT_BC5_SNORM_BLOCK; + case DataFormat::BC6H_SFLOAT_BLOCK: return VK_FORMAT_BC6H_SFLOAT_BLOCK; + case DataFormat::BC6H_UFLOAT_BLOCK: return VK_FORMAT_BC6H_UFLOAT_BLOCK; + case DataFormat::BC7_UNORM_BLOCK: return VK_FORMAT_BC7_UNORM_BLOCK; + case DataFormat::BC7_SRGB_BLOCK: return VK_FORMAT_BC7_SRGB_BLOCK; + default: + return VK_FORMAT_UNDEFINED; } } @@ -873,11 +895,6 @@ VkPipeline VKContext::GetOrCreatePipeline() { VkPipelineDepthStencilStateCreateInfo depthStencil; curDepthStencilState_->ToVulkan(&depthStencil); - VkPipelineVertexInputStateCreateInfo vertex; - VkVertexInputAttributeDescription attrDescs[4]; - VkVertexInputBindingDescription bindDescs[1]; - curVertexFormat_->ToVulkan(&vertex, attrDescs, bindDescs); - VkPipelineInputAssemblyStateCreateInfo inputAssembly = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; inputAssembly.topology = curPrim_; inputAssembly.primitiveRestartEnable = false; @@ -913,7 +930,7 @@ VkPipeline VKContext::GetOrCreatePipeline() { info.pInputAssemblyState = &inputAssembly; info.pTessellationState = nullptr; info.pMultisampleState = &ms; - info.pVertexInputState = &vertex; + info.pVertexInputState = &curInputLayout_->visc; info.pRasterizationState = &raster; info.pViewportState = &vs; // Must set viewport and scissor counts even if we set the actual state dynamically. info.layout = pipelineLayout_; @@ -966,11 +983,28 @@ void VKContext::DirtyDynamicState() { viewportDirty_ = true; } -InputLayout *VKContext::CreateVertexFormat(const std::vector &components, int stride, ShaderModule *vshader) { - VKVertexFormat *fmt = new VKVertexFormat(); - fmt->components_ = components; - fmt->stride_ = stride; - return fmt; +InputLayout *VKContext::CreateInputLayout(const InputLayoutDesc &desc) { + VKInputLayout *vl = new VKInputLayout(); + vl->visc = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; + vl->visc.flags = 0; + vl->visc.vertexAttributeDescriptionCount = (uint32_t)desc.attributes.size(); + vl->visc.vertexBindingDescriptionCount = (uint32_t)desc.bindings.size(); + vl->bindings.resize(vl->visc.vertexBindingDescriptionCount); + vl->attributes.resize(vl->visc.vertexAttributeDescriptionCount); + vl->visc.pVertexBindingDescriptions = vl->bindings.data(); + vl->visc.pVertexAttributeDescriptions = vl->attributes.data(); + for (size_t i = 0; i < desc.attributes.size(); i++) { + vl->attributes[i].binding = (uint32_t)desc.attributes[i].binding; + vl->attributes[i].format = DataFormatToVulkan(desc.attributes[i].format); + vl->attributes[i].location = desc.attributes[i].location; + vl->attributes[i].offset = desc.attributes[i].offset; + } + for (size_t i = 0; i < desc.bindings.size(); i++) { + vl->bindings[i].inputRate = desc.bindings[i].instanceRate ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; + vl->bindings[i].binding = (uint32_t)i; + vl->bindings[i].stride = desc.bindings[i].stride; + } + return vl; } Texture *VKContext::CreateTexture() { @@ -982,8 +1016,8 @@ Texture *VKContext::CreateTexture(TextureType type, DataFormat format, int width } void VKTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) { - int bpp; - VkFormat vulkanFormat = FormatToVulkan(format_, &bpp); + VkFormat vulkanFormat = DataFormatToVulkan(format_); + int bpp = GetBpp(vulkanFormat); int bytesPerPixel = bpp / 8; vkTex_->Create(width, height, vulkanFormat); int rowPitch; @@ -1108,7 +1142,7 @@ void VKContext::Draw(Primitive prim, InputLayout *format, Buffer *vdata, int ver ApplyDynamicState(); curPrim_ = PrimToVK(prim); - curVertexFormat_ = (VKVertexFormat *)format; + curInputLayout_ = (VKInputLayout *)format; Thin3DVKBuffer *vbuf = static_cast(vdata); VkBuffer vulkanVbuf; @@ -1130,7 +1164,7 @@ void VKContext::DrawIndexed(Primitive prim, InputLayout *format, Buffer *vdata, ApplyDynamicState(); curPrim_ = PrimToVK(prim); - curVertexFormat_ = (VKVertexFormat *)format; + curInputLayout_ = (VKInputLayout *)format; Thin3DVKBuffer *ibuf = static_cast(idata); Thin3DVKBuffer *vbuf = static_cast(vdata); @@ -1158,10 +1192,10 @@ void VKContext::DrawUP(Primitive prim, InputLayout *format, const void *vdata, i ApplyDynamicState(); curPrim_ = PrimToVK(prim); - curVertexFormat_ = (VKVertexFormat *)format; + curInputLayout_ = (VKInputLayout *)format; VkBuffer vulkanVbuf, vulkanUBObuf; - size_t vbBindOffset = push_->Push(vdata, vertexCount * curVertexFormat_->stride_, &vulkanVbuf); + size_t vbBindOffset = push_->Push(vdata, vertexCount * curInputLayout_->bindings[0].stride, &vulkanVbuf); uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf); VkPipeline pipeline = GetOrCreatePipeline();