mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Make buffer binding more Vulkan/Metal-like
This commit is contained in:
parent
58ecda4e4b
commit
d8dbb8389b
7 changed files with 114 additions and 64 deletions
|
@ -250,7 +250,9 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) {
|
|||
|
||||
texColor->SetMatrix4x4("WorldViewProj", identity4x4);
|
||||
thin3d->BindPipeline(texColor);
|
||||
thin3d->DrawIndexed(vdata, idata, 6, 0);
|
||||
thin3d->BindVertexBuffers(0, 1, &vdata, nullptr);
|
||||
thin3d->BindIndexBuffer(idata, 0);
|
||||
thin3d->DrawIndexed(6, 0);
|
||||
}
|
||||
|
||||
void SoftGPU::CopyDisplayToOutput()
|
||||
|
|
|
@ -94,8 +94,9 @@ void DrawBuffer::Flush(bool set_blend_state) {
|
|||
t3d_->BindPipeline(pipeline_);
|
||||
if (vbuf_) {
|
||||
vbuf_->SubData((const uint8_t *)verts_, 0, sizeof(Vertex) * count_);
|
||||
t3d_->BindVertexBuffers(0, 1, &vbuf_, nullptr);
|
||||
int offset = 0;
|
||||
t3d_->Draw(vbuf_, count_, offset);
|
||||
t3d_->Draw(count_, offset);
|
||||
} else {
|
||||
t3d_->DrawUP((const void *)verts_, count_);
|
||||
}
|
||||
|
|
|
@ -510,6 +510,9 @@ public:
|
|||
|
||||
virtual void BindSamplerStates(int start, int count, SamplerState **state) = 0;
|
||||
virtual void BindTextures(int start, int count, Texture **textures) = 0;
|
||||
virtual void BindVertexBuffers(int start, int count, Buffer **buffers, int *offsets) = 0;
|
||||
virtual void BindIndexBuffer(Buffer *indexBuffer, int offset) = 0;
|
||||
|
||||
void BindTexture(int stage, Texture *texture) {
|
||||
BindTextures(stage, 1, &texture);
|
||||
} // from sampler 0 and upwards
|
||||
|
@ -517,8 +520,8 @@ public:
|
|||
virtual void BindPipeline(Pipeline *pipeline) = 0;
|
||||
|
||||
// TODO: Add more sophisticated draws with buffer offsets, and multidraws.
|
||||
virtual void Draw(Buffer *vdata, int vertexCount, int offset) = 0;
|
||||
virtual void DrawIndexed(Buffer *vdata, Buffer *idata, int vertexCount, int offset) = 0;
|
||||
virtual void Draw(int vertexCount, int offset) = 0;
|
||||
virtual void DrawIndexed(int vertexCount, int offset) = 0;
|
||||
virtual void DrawUP(const void *vdata, int vertexCount) = 0;
|
||||
|
||||
// Render pass management. Default implementations here.
|
||||
|
|
|
@ -42,6 +42,8 @@ public:
|
|||
void BindTextures(int start, int count, Texture **textures) override;
|
||||
void BindSamplerStates(int start, int count, SamplerState **states) override;
|
||||
void BindPipeline(Pipeline *pipeline) override;
|
||||
void BindVertexBuffers(int start, int count, Buffer **buffers, int *offsets) override;
|
||||
void BindIndexBuffer(Buffer *indexBuffer, int offset) override;
|
||||
|
||||
// Raster state
|
||||
void SetScissorRect(int left, int top, int width, int height) override;
|
||||
|
@ -50,8 +52,8 @@ public:
|
|||
memcpy(blendFactor_, color, sizeof(float) * 4);
|
||||
}
|
||||
|
||||
void Draw(Buffer *vdata, int vertexCount, int offset) override;
|
||||
void DrawIndexed(Buffer *vdata, Buffer *idata, int vertexCount, int offset) override;
|
||||
void Draw(int vertexCount, int offset) override;
|
||||
void DrawIndexed(int vertexCount, int offset) override;
|
||||
void DrawUP(const void *vdata, int vertexCount) override;
|
||||
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal);
|
||||
|
||||
|
@ -458,11 +460,16 @@ Buffer *D3D11DrawContext::CreateBuffer(size_t size, uint32_t usageFlags) {
|
|||
return b;
|
||||
}
|
||||
|
||||
void D3D11DrawContext::Draw(Buffer *vdata, int vertexCount, int offset) {
|
||||
void D3D11DrawContext::BindVertexBuffers(int start, int count, Buffer **buffers, int *offsets) {
|
||||
}
|
||||
void D3D11DrawContext::BindIndexBuffer(Buffer *indexBuffer, int offset) {
|
||||
}
|
||||
|
||||
void D3D11DrawContext::Draw(int vertexCount, int offset) {
|
||||
ApplyCurrentState();
|
||||
}
|
||||
|
||||
void D3D11DrawContext::DrawIndexed(Buffer *vdata, Buffer *idata, int vertexCount, int offset) {
|
||||
void D3D11DrawContext::DrawIndexed(int vertexCount, int offset) {
|
||||
ApplyCurrentState();
|
||||
}
|
||||
|
||||
|
|
|
@ -193,18 +193,20 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class Thin3DDX9Buffer : public Buffer {
|
||||
// Simulate a simple buffer type like the other backends have, use the usage flags to create the right internal type.
|
||||
class D3D9Buffer : public Buffer {
|
||||
public:
|
||||
Thin3DDX9Buffer(LPDIRECT3DDEVICE9 device, size_t size, uint32_t flags) : vbuffer_(nullptr), ibuffer_(nullptr), maxSize_(size) {
|
||||
D3D9Buffer(LPDIRECT3DDEVICE9 device, size_t size, uint32_t flags) : vbuffer_(nullptr), ibuffer_(nullptr), maxSize_(size) {
|
||||
if (flags & BufferUsageFlag::INDEXDATA) {
|
||||
DWORD usage = D3DUSAGE_DYNAMIC;
|
||||
device->CreateIndexBuffer((UINT)size, usage, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &ibuffer_, NULL);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
DWORD usage = D3DUSAGE_DYNAMIC;
|
||||
device->CreateVertexBuffer((UINT)size, usage, 0, D3DPOOL_DEFAULT, &vbuffer_, NULL);
|
||||
}
|
||||
}
|
||||
virtual ~Thin3DDX9Buffer() override {
|
||||
virtual ~D3D9Buffer() override {
|
||||
if (ibuffer_) {
|
||||
ibuffer_->Release();
|
||||
}
|
||||
|
@ -255,22 +257,13 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
void BindAsVertexBuf(LPDIRECT3DDEVICE9 device, int vertexSize, int offset = 0) {
|
||||
if (vbuffer_)
|
||||
device->SetStreamSource(0, vbuffer_, offset, vertexSize);
|
||||
}
|
||||
void BindAsIndexBuf(LPDIRECT3DDEVICE9 device) {
|
||||
if (ibuffer_)
|
||||
device->SetIndices(ibuffer_);
|
||||
}
|
||||
|
||||
private:
|
||||
public:
|
||||
LPDIRECT3DVERTEXBUFFER9 vbuffer_;
|
||||
LPDIRECT3DINDEXBUFFER9 ibuffer_;
|
||||
size_t maxSize_;
|
||||
};
|
||||
|
||||
|
||||
class D3D9InputLayout : public InputLayout {
|
||||
public:
|
||||
D3D9InputLayout(LPDIRECT3DDEVICE9 device, const InputLayoutDesc &desc);
|
||||
|
@ -533,7 +526,18 @@ public:
|
|||
s->Apply(device_, start + i);
|
||||
}
|
||||
}
|
||||
void BindPipeline(Pipeline *pipeline) {
|
||||
void BindVertexBuffers(int start, int count, Buffer **buffers, int *offsets) override {
|
||||
for (int i = 0; i < count; i++) {
|
||||
curVBuffers_[i + start] = (D3D9Buffer *)buffers[i];
|
||||
curVBufferOffsets_[i + start] = offsets ? offsets[i] : 0;
|
||||
}
|
||||
}
|
||||
void BindIndexBuffer(Buffer *indexBuffer, int offset) override {
|
||||
curIBuffer_ = (D3D9Buffer *)indexBuffer;
|
||||
curIBufferOffset_ = offset;
|
||||
}
|
||||
|
||||
void BindPipeline(Pipeline *pipeline) override {
|
||||
curPipeline_ = (D3D9Pipeline *)pipeline;
|
||||
}
|
||||
|
||||
|
@ -542,8 +546,8 @@ public:
|
|||
void SetViewports(int count, Viewport *viewports) override;
|
||||
void SetBlendFactor(float color[4]) override;
|
||||
|
||||
void Draw(Buffer *vdata, int vertexCount, int offset) override;
|
||||
void DrawIndexed(Buffer *vdata, Buffer *idata, int vertexCount, int offset) override;
|
||||
void Draw(int vertexCount, int offset) override;
|
||||
void DrawIndexed(int vertexCount, int offset) override;
|
||||
void DrawUP(const void *vdata, int vertexCount) override;
|
||||
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal);
|
||||
|
||||
|
@ -568,8 +572,14 @@ private:
|
|||
D3DADAPTER_IDENTIFIER9 identifier_;
|
||||
D3DCAPS9 d3dCaps_;
|
||||
char shadeLangVersion_[64];
|
||||
D3D9Pipeline *curPipeline_;
|
||||
DeviceCaps caps_;
|
||||
|
||||
// Bound state
|
||||
D3D9Pipeline *curPipeline_;
|
||||
D3D9Buffer *curVBuffers_[4];
|
||||
int curVBufferOffsets_[4];
|
||||
D3D9Buffer *curIBuffer_;
|
||||
int curIBufferOffset_;
|
||||
};
|
||||
|
||||
D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx)
|
||||
|
@ -768,7 +778,7 @@ D3D9InputLayout::D3D9InputLayout(LPDIRECT3DDEVICE9 device, const InputLayoutDesc
|
|||
}
|
||||
|
||||
Buffer *D3D9Context::CreateBuffer(size_t size, uint32_t usageFlags) {
|
||||
return new Thin3DDX9Buffer(device_, size, usageFlags);
|
||||
return new D3D9Buffer(device_, size, usageFlags);
|
||||
}
|
||||
|
||||
void D3D9Pipeline::Apply(LPDIRECT3DDEVICE9 device) {
|
||||
|
@ -779,23 +789,21 @@ void D3D9Pipeline::Apply(LPDIRECT3DDEVICE9 device) {
|
|||
raster->Apply(device);
|
||||
}
|
||||
|
||||
void D3D9Context::Draw(Buffer *vdata, int vertexCount, int offset) {
|
||||
Thin3DDX9Buffer *vbuf = static_cast<Thin3DDX9Buffer *>(vdata);
|
||||
|
||||
vbuf->BindAsVertexBuf(device_, curPipeline_->inputLayout->GetStride(0), offset);
|
||||
void D3D9Context::Draw(int vertexCount, int offset) {
|
||||
device_->SetStreamSource(0, curVBuffers_[0]->vbuffer_, curVBufferOffsets_[0], curPipeline_->inputLayout->GetStride(0));
|
||||
curPipeline_->Apply(device_);
|
||||
curPipeline_->inputLayout->Apply(device_);
|
||||
device_->DrawPrimitive(curPipeline_->prim, offset, vertexCount / 3);
|
||||
}
|
||||
|
||||
void D3D9Context::DrawIndexed(Buffer *vdata, Buffer *idata, int vertexCount, int offset) {
|
||||
Thin3DDX9Buffer *vbuf = static_cast<Thin3DDX9Buffer *>(vdata);
|
||||
Thin3DDX9Buffer *ibuf = static_cast<Thin3DDX9Buffer *>(idata);
|
||||
void D3D9Context::DrawIndexed(int vertexCount, int offset) {
|
||||
D3D9Buffer *vbuf = static_cast<D3D9Buffer *>(curVBuffers_[0]);
|
||||
D3D9Buffer *ibuf = static_cast<D3D9Buffer *>(curIBuffer_);
|
||||
|
||||
curPipeline_->Apply(device_);
|
||||
curPipeline_->inputLayout->Apply(device_);
|
||||
vbuf->BindAsVertexBuf(device_, curPipeline_->inputLayout->GetStride(0), offset);
|
||||
ibuf->BindAsIndexBuf(device_);
|
||||
device_->SetStreamSource(0, curVBuffers_[0]->vbuffer_, curVBufferOffsets_[0], curPipeline_->inputLayout->GetStride(0));
|
||||
device_->SetIndices(curIBuffer_->ibuffer_);
|
||||
device_->DrawIndexedPrimitive(curPipeline_->prim, 0, 0, vertexCount, 0, vertexCount / curPipeline_->primDivisor);
|
||||
}
|
||||
|
||||
|
|
|
@ -284,13 +284,13 @@ public:
|
|||
}
|
||||
|
||||
void SetData(const uint8_t *data, size_t size) override {
|
||||
Bind();
|
||||
Bind(0);
|
||||
glBufferData(target_, size, data, usage_);
|
||||
knownSize_ = size;
|
||||
}
|
||||
|
||||
void SubData(const uint8_t *data, size_t offset, size_t size) override {
|
||||
Bind();
|
||||
Bind(0);
|
||||
if (size + offset > knownSize_) {
|
||||
// Allocate the buffer.
|
||||
glBufferData(target_, size + offset, NULL, usage_);
|
||||
|
@ -298,7 +298,8 @@ public:
|
|||
}
|
||||
glBufferSubData(target_, offset, size, data);
|
||||
}
|
||||
void Bind() {
|
||||
void Bind(int offset) {
|
||||
// TODO: Can't support offset using ES 2.0
|
||||
glBindBuffer(target_, buffer_);
|
||||
}
|
||||
|
||||
|
@ -555,11 +556,22 @@ public:
|
|||
|
||||
void BindTextures(int start, int count, Texture **textures) override;
|
||||
void BindPipeline(Pipeline *pipeline) override;
|
||||
void BindVertexBuffers(int start, int count, Buffer **buffers, int *offsets) override {
|
||||
for (int i = 0; i < count; i++) {
|
||||
curVBuffers_[i + start] = (OpenGLBuffer *)buffers[i];
|
||||
curVBufferOffsets_[i + start] = offsets ? offsets[i] : 0;
|
||||
}
|
||||
}
|
||||
void BindIndexBuffer(Buffer *indexBuffer, int offset) override {
|
||||
curIBuffer_ = (OpenGLBuffer *)indexBuffer;
|
||||
curIBufferOffset_ = offset;
|
||||
}
|
||||
|
||||
// TODO: Add more sophisticated draws.
|
||||
void Draw(Buffer *vdata, int vertexCount, int offset) override;
|
||||
void DrawIndexed(Buffer *vdata, Buffer *idata, int vertexCount, int offset) override;
|
||||
void Draw(int vertexCount, int offset) override;
|
||||
void DrawIndexed(int vertexCount, int offset) override;
|
||||
void DrawUP(const void *vdata, int vertexCount) override;
|
||||
|
||||
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
|
||||
|
||||
std::string GetInfoString(InfoField info) const override {
|
||||
|
@ -594,8 +606,14 @@ public:
|
|||
}
|
||||
|
||||
std::vector<OpenGLSamplerState *> samplerStates_;
|
||||
OpenGLPipeline *curPipeline_;
|
||||
DeviceCaps caps_;
|
||||
|
||||
// Bound state
|
||||
OpenGLPipeline *curPipeline_;
|
||||
OpenGLBuffer *curVBuffers_[4];
|
||||
int curVBufferOffsets_[4];
|
||||
OpenGLBuffer *curIBuffer_;
|
||||
int curIBufferOffset_;
|
||||
};
|
||||
|
||||
OpenGLContext::OpenGLContext() {
|
||||
|
@ -1008,10 +1026,8 @@ void OpenGLContext::BindPipeline(Pipeline *pipeline) {
|
|||
curPipeline_->raster->Apply();
|
||||
}
|
||||
|
||||
void OpenGLContext::Draw(Buffer *vdata, int vertexCount, int offset) {
|
||||
OpenGLBuffer *vbuf = static_cast<OpenGLBuffer *>(vdata);
|
||||
|
||||
vbuf->Bind();
|
||||
void OpenGLContext::Draw(int vertexCount, int offset) {
|
||||
curVBuffers_[0]->Bind(curVBufferOffsets_[0]);
|
||||
curPipeline_->inputLayout->Apply();
|
||||
curPipeline_->Apply();
|
||||
|
||||
|
@ -1021,15 +1037,12 @@ void OpenGLContext::Draw(Buffer *vdata, int vertexCount, int offset) {
|
|||
curPipeline_->inputLayout->Unapply();
|
||||
}
|
||||
|
||||
void OpenGLContext::DrawIndexed(Buffer *vdata, Buffer *idata, int vertexCount, int offset) {
|
||||
OpenGLBuffer *vbuf = static_cast<OpenGLBuffer *>(vdata);
|
||||
OpenGLBuffer *ibuf = static_cast<OpenGLBuffer *>(idata);
|
||||
|
||||
vbuf->Bind();
|
||||
void OpenGLContext::DrawIndexed(int vertexCount, int offset) {
|
||||
curVBuffers_[0]->Bind(curVBufferOffsets_[0]);
|
||||
curPipeline_->inputLayout->Apply();
|
||||
curPipeline_->Apply();
|
||||
// Note: ibuf binding is stored in the VAO, so call this after binding the fmt.
|
||||
ibuf->Bind();
|
||||
curIBuffer_->Bind(curIBufferOffset_);
|
||||
|
||||
glDrawElements(curPipeline_->prim, vertexCount, GL_UNSIGNED_INT, (const void *)(size_t)offset);
|
||||
|
||||
|
|
|
@ -177,12 +177,12 @@ public:
|
|||
|
||||
// Very simplistic buffer that will simply copy its contents into our "pushbuffer" when it's time to draw,
|
||||
// to avoid synchronization issues.
|
||||
class Thin3DVKBuffer : public Buffer {
|
||||
class VKBuffer : public Buffer {
|
||||
public:
|
||||
Thin3DVKBuffer(size_t size, uint32_t flags) : dataSize_(size) {
|
||||
VKBuffer(size_t size, uint32_t flags) : dataSize_(size) {
|
||||
data_ = new uint8_t[size];
|
||||
}
|
||||
~Thin3DVKBuffer() override {
|
||||
~VKBuffer() override {
|
||||
delete[] data_;
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ public:
|
|||
size_t GetSize() const { return dataSize_; }
|
||||
const uint8_t *GetData() const { return data_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
uint8_t *data_;
|
||||
size_t dataSize_;
|
||||
};
|
||||
|
@ -376,9 +376,21 @@ public:
|
|||
curPipeline_ = (VKPipeline *)pipeline;
|
||||
}
|
||||
|
||||
// TODO: Make VKBuffers proper buffers, and do a proper binding model. This is just silly.
|
||||
void BindVertexBuffers(int start, int count, Buffer **buffers, int *offsets) override {
|
||||
for (int i = 0; i < count; i++) {
|
||||
curVBuffers_[i + start] = (VKBuffer *)buffers[i];
|
||||
curVBufferOffsets_[i + start] = offsets ? offsets[i] : 0;
|
||||
}
|
||||
}
|
||||
void BindIndexBuffer(Buffer *indexBuffer, int offset) override {
|
||||
curIBuffer_ = (VKBuffer *)indexBuffer;
|
||||
curIBufferOffset_ = offset;
|
||||
}
|
||||
|
||||
// TODO: Add more sophisticated draws.
|
||||
void Draw(Buffer *vdata, int vertexCount, int offset) override;
|
||||
void DrawIndexed(Buffer *vdata, Buffer *idata, int vertexCount, int offset) override;
|
||||
void Draw(int vertexCount, int offset) override;
|
||||
void DrawIndexed(int vertexCount, int offset) override;
|
||||
void DrawUP(const void *vdata, int vertexCount) override;
|
||||
|
||||
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
|
||||
|
@ -414,6 +426,10 @@ private:
|
|||
VulkanContext *vulkan_;
|
||||
|
||||
VKPipeline *curPipeline_;
|
||||
VKBuffer *curVBuffers_[4];
|
||||
int curVBufferOffsets_[4];
|
||||
VKBuffer *curIBuffer_;
|
||||
int curIBufferOffset_;
|
||||
|
||||
VkDescriptorSetLayout descriptorSetLayout_;
|
||||
VkPipelineLayout pipelineLayout_;
|
||||
|
@ -1001,7 +1017,7 @@ BlendState *VKContext::CreateBlendState(const BlendStateDesc &desc) {
|
|||
}
|
||||
|
||||
Buffer *VKContext::CreateBuffer(size_t size, uint32_t usageFlags) {
|
||||
return new Thin3DVKBuffer(size, usageFlags);
|
||||
return new VKBuffer(size, usageFlags);
|
||||
}
|
||||
|
||||
void VKContext::BindTextures(int start, int count, Texture **textures) {
|
||||
|
@ -1061,10 +1077,10 @@ inline VkPrimitiveTopology PrimToVK(Primitive prim) {
|
|||
}
|
||||
}
|
||||
|
||||
void VKContext::Draw(Buffer *vdata, int vertexCount, int offset) {
|
||||
void VKContext::Draw(int vertexCount, int offset) {
|
||||
ApplyDynamicState();
|
||||
|
||||
Thin3DVKBuffer *vbuf = static_cast<Thin3DVKBuffer *>(vdata);
|
||||
VKBuffer *vbuf = curVBuffers_[0];
|
||||
|
||||
VkBuffer vulkanVbuf;
|
||||
VkBuffer vulkanUBObuf;
|
||||
|
@ -1080,11 +1096,11 @@ void VKContext::Draw(Buffer *vdata, int vertexCount, int offset) {
|
|||
vkCmdDraw(cmd_, vertexCount, 1, offset, 0);
|
||||
}
|
||||
|
||||
void VKContext::DrawIndexed(Buffer *vdata, Buffer *idata, int vertexCount, int offset) {
|
||||
void VKContext::DrawIndexed(int vertexCount, int offset) {
|
||||
ApplyDynamicState();
|
||||
|
||||
Thin3DVKBuffer *ibuf = static_cast<Thin3DVKBuffer *>(idata);
|
||||
Thin3DVKBuffer *vbuf = static_cast<Thin3DVKBuffer *>(vdata);
|
||||
VKBuffer *ibuf = static_cast<VKBuffer *>(curIBuffer_);
|
||||
VKBuffer *vbuf = static_cast<VKBuffer *>(curVBuffers_[0]);
|
||||
|
||||
VkBuffer vulkanVbuf, vulkanIbuf, vulkanUBObuf;
|
||||
uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf);
|
||||
|
|
Loading…
Add table
Reference in a new issue