mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 15:00:30 +02:00
More modern way to specify vertex data format (inputlayout)
This commit is contained in:
1 parent
166243e0fd
commit
1ed7f0d7fd
7 files changed
+181
-128
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user