More modern way to specify vertex data format (inputlayout)

This commit is contained in:
Henrik Rydgård committed 2016-12-27 11:59:10 +01:00
1 parent 166243e0fd
commit 1ed7f0d7fd
7 files changed
+181 -128

No files matched your search

+11 -5
View File
@@ -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<VertexComponent> 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);
+2 -1
View File
@@ -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();
+11 -7
View File
@@ -41,14 +41,18 @@ void DrawBuffer::Init(Draw::DrawContext *t3d) {
t3d_ = t3d;
inited_ = true;
std::vector<VertexComponent> 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 {
+16 -13
View File
@@ -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<BindingDesc> bindings;
std::vector<AttributeDesc> 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<VertexComponent> &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;
+29 -25
View File
@@ -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<VertexComponent> &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<VertexComponent> &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<Thin3DDX9DepthStencilState *>(state);
D3D9DepthStencilState *bs = static_cast<D3D9DepthStencilState *>(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<VertexComponent> &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<VertexComponent> &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<Thin3DDX9Buffer *>(vdata);
Thin3DDX9VertexFormat *fmt = static_cast<Thin3DDX9VertexFormat *>(format);
D3D9InputLayout *fmt = static_cast<D3D9InputLayout *>(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<Thin3DDX9Buffer *>(vdata);
Thin3DDX9Buffer *ibuf = static_cast<Thin3DDX9Buffer *>(idata);
Thin3DDX9VertexFormat *fmt = static_cast<Thin3DDX9VertexFormat *>(format);
D3D9InputLayout *fmt = static_cast<D3D9InputLayout *>(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<Thin3DDX9VertexFormat *>(format);
D3D9InputLayout *fmt = static_cast<D3D9InputLayout *>(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) {
+29 -28
View File
@@ -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<VertexComponent> 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<VertexComponent> &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<VertexComponent> &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<OpenGLBuffer *>(vdata);
OpenGLVertexFormat *fmt = static_cast<OpenGLVertexFormat *>(format);
OpenGLInputLayout *fmt = static_cast<OpenGLInputLayout *>(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<OpenGLBuffer *>(vdata);
OpenGLBuffer *ibuf = static_cast<OpenGLBuffer *>(idata);
OpenGLVertexFormat *fmt = static_cast<OpenGLVertexFormat *>(format);
OpenGLInputLayout *fmt = static_cast<OpenGLInputLayout *>(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<OpenGLVertexFormat *>(format);
OpenGLInputLayout *fmt = static_cast<OpenGLInputLayout *>(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)) {
+83 -49
View File
@@ -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<VertexComponent> components_;
int stride_;
std::vector<VkVertexInputBindingDescription> bindings;
std::vector<VkVertexInputAttributeDescription> 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<VertexComponent> &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<VertexComponent> &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<Thin3DVKBuffer *>(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<Thin3DVKBuffer *>(idata);
Thin3DVKBuffer *vbuf = static_cast<Thin3DVKBuffer *>(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();