DrawContext: Use uniform buffers on all platforms (simulated where necessary)

This commit is contained in:
Henrik Rydgard 2017-02-08 12:55:58 +01:00
parent fe1b593c15
commit 9bdae8f32e
8 changed files with 43 additions and 34 deletions

View file

@ -94,7 +94,7 @@ SoftGPU::SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
PipelineDesc pipelineDesc{
Primitive::TRIANGLE_LIST,
{ draw_->GetVshaderPreset(VS_TEXTURE_COLOR_2D), draw_->GetFshaderPreset(FS_TEXTURE_COLOR_2D) },
inputLayout, depth, blendstateOff, rasterNoCull
inputLayout, depth, blendstateOff, rasterNoCull, &vsTexColBufDesc
};
texColor = draw_->CreateGraphicsPipeline(pipelineDesc);
@ -250,8 +250,10 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) {
0.0f, 0.0f, 0.0f, 1.0f,
};
texColor->SetMatrix4x4("WorldViewProj", identity4x4);
VsTexColUB ub{};
memcpy(ub.WorldViewProj, identity4x4, sizeof(float) * 16);
draw_->BindPipeline(texColor);
draw_->UpdateDynamicUniformBuffer(&ub, sizeof(ub));
draw_->BindVertexBuffers(0, 1, &vdata, nullptr);
draw_->BindIndexBuffer(idata, 0);
draw_->DrawIndexed(6, 0);

View file

@ -596,12 +596,12 @@ void NativeInitGraphics(GraphicsContext *graphicsContext) {
PipelineDesc colorDesc{
Primitive::TRIANGLE_LIST,
{ g_draw->GetVshaderPreset(VS_COLOR_2D), g_draw->GetFshaderPreset(FS_COLOR_2D) },
inputLayout, depth, blendNormal, rasterNoCull
inputLayout, depth, blendNormal, rasterNoCull, &vsColBufDesc,
};
PipelineDesc texColorDesc{
Primitive::TRIANGLE_LIST,
{ g_draw->GetVshaderPreset(VS_TEXTURE_COLOR_2D), g_draw->GetFshaderPreset(FS_TEXTURE_COLOR_2D) },
inputLayout, depth, blendNormal, rasterNoCull
inputLayout, depth, blendNormal, rasterNoCull, &vsTexColBufDesc,
};
colorPipeline = g_draw->CreateGraphicsPipeline(colorDesc);

View file

@ -90,8 +90,12 @@ void DrawBuffer::Flush(bool set_blend_state) {
if (count_ == 0)
return;
pipeline_->SetMatrix4x4("WorldViewProj", drawMatrix_.getReadPtr());
draw_->BindPipeline(pipeline_);
VsTexColUB ub{};
memcpy(ub.WorldViewProj, drawMatrix_.getReadPtr(), sizeof(Matrix4x4));
// pipeline_->SetMatrix4x4("WorldViewProj", drawMatrix_.getReadPtr());
draw_->UpdateDynamicUniformBuffer(&ub, sizeof(ub));
if (vbuf_) {
draw_->UpdateBuffer(vbuf_, (const uint8_t *)verts_, 0, sizeof(Vertex) * count_, Draw::UPDATE_DISCARD);
draw_->BindVertexBuffers(0, 1, &vbuf_, nullptr);

View file

@ -522,7 +522,7 @@ struct PipelineDesc {
DepthStencilState *depthStencil;
BlendState *blend;
RasterState *raster;
UniformBufferDesc *uniformDesc;
const UniformBufferDesc *uniformDesc;
};
struct DeviceCaps {

View file

@ -729,14 +729,14 @@ Pipeline *D3D11DrawContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
dPipeline->dynamicUniformsSize = desc.uniformDesc->uniformBufferSize;
D3D11_BUFFER_DESC bufdesc{};
bufdesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bufdesc.ByteWidth = dPipeline->dynamicUniformsSize;
bufdesc.StructureByteStride = dPipeline->dynamicUniformsSize;
bufdesc.ByteWidth = (UINT)dPipeline->dynamicUniformsSize;
bufdesc.StructureByteStride = (UINT)dPipeline->dynamicUniformsSize;
bufdesc.Usage = D3D11_USAGE_DYNAMIC;
bufdesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
HRESULT hr = device_->CreateBuffer(&bufdesc, nullptr, &dPipeline->dynamicUniforms);
D3D11_SHADER_RESOURCE_VIEW_DESC bufview{};
bufview.Buffer.ElementOffset = 0;
bufview.Buffer.ElementWidth = dPipeline->dynamicUniformsSize;
bufview.Buffer.ElementWidth = (UINT)dPipeline->dynamicUniformsSize;
bufview.Buffer.FirstElement = 0;
bufview.Buffer.NumElements = 1;
hr = device_->CreateShaderResourceView(dPipeline->dynamicUniforms, &bufview, &dPipeline->dynamicUniformsView);
@ -836,6 +836,10 @@ void D3D11DrawContext::ApplyCurrentState() {
if (nextIndexBuffer_) {
context_->IASetIndexBuffer(nextIndexBuffer_, DXGI_FORMAT_R32_UINT, nextIndexBufferOffset_);
}
if (curPipeline_->dynamicUniforms) {
context_->VSSetShaderResources(0, 1, &curPipeline_->dynamicUniformsView);
}
}
class D3D11Buffer : public Buffer {

View file

@ -816,6 +816,14 @@ Buffer *D3D9Context::CreateBuffer(size_t size, uint32_t usageFlags) {
return new D3D9Buffer(device_, size, usageFlags);
}
inline void Transpose4x4(float out[16], const float in[16]) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
out[i * 4 + j] = in[j * 4 + i];
}
}
}
void D3D9Context::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
if (size != curPipeline_->dynamicUniforms.uniformBufferSize)
Crash();
@ -829,9 +837,11 @@ void D3D9Context::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
count = 4;
break;
}
const float *srcPtr = (const float *)((uint8_t *)ub + uniform.offset);
const float *srcPtr = (const float *)((const uint8_t *)ub + uniform.offset);
if (uniform.vertexReg != -1) {
device_->SetVertexShaderConstantF(uniform.vertexReg, srcPtr, count);
float transp[16];
Transpose4x4(transp, srcPtr);
device_->SetVertexShaderConstantF(uniform.vertexReg, transp, count);
}
if (uniform.fragmentReg != -1) {
device_->SetPixelShaderConstantF(uniform.fragmentReg, srcPtr, count);

View file

@ -404,9 +404,6 @@ public:
bool LinkShaders();
void Apply();
void Unapply();
int GetUniformLoc(const char *name);
void SetVector(const char *name, float *value, int n) override;
@ -436,8 +433,8 @@ public:
// TODO: Optimize by getting the locations first and putting in a custom struct
UniformBufferDesc dynamicUniforms;
private:
GLuint program_;
private:
std::map<std::string, UniformInfo> uniformCache_;
};
@ -515,7 +512,7 @@ public:
void SetViewports(int count, Viewport *viewports) override {
// TODO: Use glViewportArrayv.
glViewport(viewports[0].TopLeftX, viewports[0].TopLeftY, viewports[0].Width, viewports[0].Height);
glViewport((GLint)viewports[0].TopLeftX, (GLint)viewports[0].TopLeftY, (GLsizei)viewports[0].Width, (GLsizei)viewports[0].Height);
#if defined(USING_GLES2)
glDepthRangef(viewports[0].MinDepth, viewports[0].MaxDepth);
#else
@ -769,6 +766,11 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int
ELOG("Thin3d GL: Unsupported texture format %d", (int)format_);
return;
}
/*
GLenum err = glGetError();
if (err) {
ELOG("Thin3D GL: Error before loading texture: %08x", err);
}*/
Bind();
switch (target_) {
@ -780,9 +782,9 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int
break;
}
GLenum err = glGetError();
if (err) {
ELOG("Thin3D GL: Error loading texture: %08x", err);
GLenum err2 = glGetError();
if (err2) {
ELOG("Thin3D GL: Error loading texture: %08x", err2);
}
}
@ -1086,19 +1088,12 @@ void OpenGLPipeline::SetMatrix4x4(const char *name, const float value[16]) {
}
}
void OpenGLPipeline::Apply() {
glUseProgram(program_);
}
void OpenGLPipeline::Unapply() {
glUseProgram(0);
}
void OpenGLContext::BindPipeline(Pipeline *pipeline) {
curPipeline_ = (OpenGLPipeline *)pipeline;
curPipeline_->blend->Apply();
curPipeline_->depthStencil->Apply();
curPipeline_->raster->Apply();
glUseProgram(curPipeline_->program_);
}
void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
@ -1125,36 +1120,30 @@ void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
void OpenGLContext::Draw(int vertexCount, int offset) {
curVBuffers_[0]->Bind(curVBufferOffsets_[0]);
curPipeline_->inputLayout->Apply();
curPipeline_->Apply();
glDrawArrays(curPipeline_->prim, offset, vertexCount);
curPipeline_->Unapply();
curPipeline_->inputLayout->Unapply();
}
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.
curIBuffer_->Bind(curIBufferOffset_);
glDrawElements(curPipeline_->prim, vertexCount, GL_UNSIGNED_INT, (const void *)(size_t)offset);
curPipeline_->Unapply();
curPipeline_->inputLayout->Unapply();
}
void OpenGLContext::DrawUP(const void *vdata, int vertexCount) {
curPipeline_->inputLayout->Apply(vdata);
curPipeline_->Apply();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDrawArrays(curPipeline_->prim, 0, vertexCount);
curPipeline_->Unapply();
curPipeline_->inputLayout->Unapply();
}

View file

@ -263,7 +263,7 @@ public:
class VKPipeline : public Pipeline {
public:
VKPipeline(size_t size) {
uboSize_ = size;
uboSize_ = (int)size;
ubo_ = new uint8_t[uboSize_];
}
~VKPipeline() {