Merge pull request #14162 from unknownbrackets/thin3d-autoref

Draw: Auto ref/release bound textures/samplers
This commit is contained in:
Henrik Rydgård 2021-02-17 09:50:33 +01:00 committed by GitHub
commit 880b3432f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 83 additions and 75 deletions

View File

@ -185,7 +185,7 @@ private:
ID3D11Texture2D *bbDepthStencilTex_ = nullptr;
ID3D11DepthStencilView *bbDepthStencilView_ = nullptr;
Framebuffer *curRenderTarget_ = nullptr;
AutoRef<Framebuffer> curRenderTarget_;
ID3D11RenderTargetView *curRenderTargetView_ = nullptr;
ID3D11DepthStencilView *curDepthStencilView_ = nullptr;
// Needed to rotate stencil/viewport rectangles properly
@ -194,12 +194,12 @@ private:
int curRTWidth_ = 0;
int curRTHeight_ = 0;
D3D11Pipeline *curPipeline_ = nullptr;
AutoRef<D3D11Pipeline> curPipeline_;
DeviceCaps caps_{};
D3D11BlendState *curBlend_ = nullptr;
D3D11DepthStencilState *curDepth_ = nullptr;
D3D11RasterState *curRaster_ = nullptr;
AutoRef<D3D11BlendState> curBlend_;
AutoRef<D3D11DepthStencilState> curDepth_;
AutoRef<D3D11RasterState> curRaster_;
ID3D11InputLayout *curInputLayout_ = nullptr;
ID3D11VertexShader *curVS_ = nullptr;
ID3D11PixelShader *curPS_ = nullptr;
@ -696,14 +696,6 @@ public:
class D3D11Pipeline : public Pipeline {
public:
~D3D11Pipeline() {
if (input)
input->Release();
if (blend)
blend->Release();
if (depth)
depth->Release();
if (raster)
raster->Release();
if (il)
il->Release();
if (dynamicUniforms)
@ -716,11 +708,11 @@ public:
return true;
}
D3D11InputLayout *input = nullptr;
AutoRef<D3D11InputLayout> input;
ID3D11InputLayout *il = nullptr;
D3D11BlendState *blend = nullptr;
D3D11DepthStencilState *depth = nullptr;
D3D11RasterState *raster = nullptr;
AutoRef<D3D11BlendState> blend;
AutoRef<D3D11DepthStencilState> depth;
AutoRef<D3D11RasterState> raster;
ID3D11VertexShader *vs = nullptr;
ID3D11PixelShader *ps = nullptr;
ID3D11GeometryShader *gs = nullptr;
@ -975,12 +967,6 @@ Pipeline *D3D11DrawContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
dPipeline->depth = (D3D11DepthStencilState *)desc.depthStencil;
dPipeline->input = (D3D11InputLayout *)desc.inputLayout;
dPipeline->raster = (D3D11RasterState *)desc.raster;
dPipeline->blend->AddRef();
dPipeline->depth->AddRef();
if (dPipeline->input) {
dPipeline->input->AddRef();
}
dPipeline->raster->AddRef();
dPipeline->topology = primToD3D11[(int)desc.prim];
if (desc.uniformDesc) {
dPipeline->dynamicUniformsSize = desc.uniformDesc->uniformBufferSize;
@ -1026,7 +1012,7 @@ Pipeline *D3D11DrawContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
}
// Can finally create the input layout
if (dPipeline->input) {
if (dPipeline->input != nullptr) {
const std::vector<D3D11_INPUT_ELEMENT_DESC> &elements = dPipeline->input->elements;
HRESULT hr = device_->CreateInputLayout(elements.data(), (UINT)elements.size(), vshader->byteCode_.data(), vshader->byteCode_.size(), &dPipeline->il);
if (!SUCCEEDED(hr)) {
@ -1104,7 +1090,7 @@ void D3D11DrawContext::ApplyCurrentState() {
curTopology_ = curPipeline_->topology;
}
if (curPipeline_->input) {
if (curPipeline_->input != nullptr) {
int numVBs = (int)curPipeline_->input->strides.size();
context_->IASetVertexBuffers(0, numVBs, nextVertexBuffers_, (UINT *)curPipeline_->input->strides.data(), (UINT *)nextVertexBufferOffsets_);
}
@ -1378,13 +1364,13 @@ void D3D11DrawContext::Clear(int mask, uint32_t colorval, float depthVal, int st
void D3D11DrawContext::BeginFrame() {
context_->OMSetRenderTargets(1, &curRenderTargetView_, curDepthStencilView_);
if (curBlend_) {
if (curBlend_ != nullptr) {
context_->OMSetBlendState(curBlend_->bs, blendFactor_, 0xFFFFFFFF);
}
if (curDepth_) {
if (curDepth_ != nullptr) {
context_->OMSetDepthStencilState(curDepth_->dss, stencilRef_);
}
if (curRaster_) {
if (curRaster_ != nullptr) {
context_->RSSetState(curRaster_->rs);
}
context_->IASetInputLayout(curInputLayout_);
@ -1394,7 +1380,7 @@ void D3D11DrawContext::BeginFrame() {
if (curTopology_ != D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED) {
context_->IASetPrimitiveTopology(curTopology_);
}
if (curPipeline_) {
if (curPipeline_ != nullptr) {
context_->IASetVertexBuffers(0, 1, nextVertexBuffers_, (UINT *)curPipeline_->input->strides.data(), (UINT *)nextVertexBufferOffsets_);
context_->IASetIndexBuffer(nextIndexBuffer_, DXGI_FORMAT_R16_UINT, nextIndexBufferOffset_);
if (curPipeline_->dynamicUniforms) {

View File

@ -273,10 +273,6 @@ class D3D9Pipeline : public Pipeline {
public:
D3D9Pipeline() {}
~D3D9Pipeline() {
if (depthStencil) depthStencil->Release();
if (blend) blend->Release();
if (raster) raster->Release();
if (inputLayout) inputLayout->Release();
}
bool RequiresBuffer() override {
return false;
@ -287,10 +283,10 @@ public:
D3DPRIMITIVETYPE prim;
int primDivisor;
D3D9InputLayout *inputLayout = nullptr;
D3D9DepthStencilState *depthStencil = nullptr;
D3D9BlendState *blend = nullptr;
D3D9RasterState *raster = nullptr;
AutoRef<D3D9InputLayout> inputLayout;
AutoRef<D3D9DepthStencilState> depthStencil;
AutoRef<D3D9BlendState> blend;
AutoRef<D3D9RasterState> raster;
UniformBufferDesc dynamicUniforms;
void Apply(LPDIRECT3DDEVICE9 device);
@ -610,12 +606,12 @@ private:
DeviceCaps caps_{};
// Bound state
D3D9Pipeline *curPipeline_ = nullptr;
D3D9Buffer *curVBuffers_[4]{};
AutoRef<D3D9Pipeline> curPipeline_;
AutoRef<D3D9Buffer> curVBuffers_[4];
int curVBufferOffsets_[4]{};
D3D9Buffer *curIBuffer_ = nullptr;
AutoRef<D3D9Buffer> curIBuffer_;
int curIBufferOffset_ = 0;
Framebuffer *curRenderTarget_ = nullptr;
AutoRef<Framebuffer> curRenderTarget_;
// Framebuffer state
LPDIRECT3DSURFACE9 deviceRTsurf = 0;
@ -713,10 +709,6 @@ Pipeline *D3D9Context::CreateGraphicsPipeline(const PipelineDesc &desc) {
pipeline->blend = (D3D9BlendState *)desc.blend;
pipeline->raster = (D3D9RasterState *)desc.raster;
pipeline->inputLayout = (D3D9InputLayout *)desc.inputLayout;
pipeline->depthStencil->AddRef();
pipeline->blend->AddRef();
pipeline->raster->AddRef();
pipeline->inputLayout->AddRef();
if (desc.uniformDesc)
pipeline->dynamicUniforms = *desc.uniformDesc;
return pipeline;

View File

@ -281,10 +281,6 @@ public:
iter->Release();
}
if (program_) render_->DeleteProgram(program_);
if (depthStencil) depthStencil->Release();
if (blend) blend->Release();
if (raster) raster->Release();
if (inputLayout) inputLayout->Release();
}
bool LinkShaders();
@ -295,10 +291,10 @@ public:
GLuint prim = 0;
std::vector<OpenGLShaderModule *> shaders;
OpenGLInputLayout *inputLayout = nullptr;
OpenGLDepthStencilState *depthStencil = nullptr;
OpenGLBlendState *blend = nullptr;
OpenGLRasterState *raster = nullptr;
AutoRef<OpenGLInputLayout> inputLayout;
AutoRef<OpenGLDepthStencilState> depthStencil;
AutoRef<OpenGLBlendState> blend;
AutoRef<OpenGLRasterState> raster;
// TODO: Optimize by getting the locations first and putting in a custom struct
UniformBufferDesc dynamicUniforms;
@ -406,7 +402,7 @@ public:
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];
curVBuffers_[i + start] = (OpenGLBuffer *)buffers[i];
curVBufferOffsets_[i + start] = offsets ? offsets[i] : 0;
}
}
@ -482,17 +478,17 @@ private:
DeviceCaps caps_{};
// Bound state
OpenGLSamplerState *boundSamplers_[MAX_TEXTURE_SLOTS]{};
AutoRef<OpenGLSamplerState> boundSamplers_[MAX_TEXTURE_SLOTS];
// Point to GLRTexture directly because they can point to the textures
// in framebuffers too (which also can be bound).
const GLRTexture *boundTextures_[MAX_TEXTURE_SLOTS]{};
OpenGLPipeline *curPipeline_ = nullptr;
OpenGLBuffer *curVBuffers_[4]{};
AutoRef<OpenGLPipeline> curPipeline_;
AutoRef<OpenGLBuffer> curVBuffers_[4]{};
int curVBufferOffsets_[4]{};
OpenGLBuffer *curIBuffer_ = nullptr;
AutoRef<OpenGLBuffer> curIBuffer_;
int curIBufferOffset_ = 0;
Framebuffer *curRenderTarget_ = nullptr;
AutoRef<Framebuffer> curRenderTarget_;
uint8_t stencilRef_ = 0;
@ -1069,12 +1065,6 @@ Pipeline *OpenGLContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
pipeline->blend = (OpenGLBlendState *)desc.blend;
pipeline->raster = (OpenGLRasterState *)desc.raster;
pipeline->inputLayout = (OpenGLInputLayout *)desc.inputLayout;
pipeline->depthStencil->AddRef();
pipeline->blend->AddRef();
pipeline->raster->AddRef();
if (pipeline->inputLayout) {
pipeline->inputLayout->AddRef();
}
return pipeline;
} else {
ERROR_LOG(G3D, "Failed to create pipeline - shaders failed to link");
@ -1210,7 +1200,7 @@ void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
}
void OpenGLContext::Draw(int vertexCount, int offset) {
_dbg_assert_msg_(curVBuffers_[0], "Can't call Draw without a vertex buffer");
_dbg_assert_msg_(curVBuffers_[0] != nullptr, "Can't call Draw without a vertex buffer");
ApplySamplers();
if (curPipeline_->inputLayout) {
renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]);
@ -1219,8 +1209,8 @@ void OpenGLContext::Draw(int vertexCount, int offset) {
}
void OpenGLContext::DrawIndexed(int vertexCount, int offset) {
_dbg_assert_msg_(curVBuffers_[0], "Can't call DrawIndexed without a vertex buffer");
_dbg_assert_msg_(curIBuffer_, "Can't call DrawIndexed without an index buffer");
_dbg_assert_msg_(curVBuffers_[0] != nullptr, "Can't call DrawIndexed without a vertex buffer");
_dbg_assert_msg_(curIBuffer_ != nullptr, "Can't call DrawIndexed without an index buffer");
ApplySamplers();
if (curPipeline_->inputLayout) {
renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]);
@ -1230,7 +1220,7 @@ void OpenGLContext::DrawIndexed(int vertexCount, int offset) {
}
void OpenGLContext::DrawUP(const void *vdata, int vertexCount) {
_assert_(curPipeline_->inputLayout);
_assert_(curPipeline_->inputLayout != nullptr);
int stride = curPipeline_->inputLayout->stride;
size_t dataSize = stride * vertexCount;

View File

@ -511,16 +511,16 @@ private:
VulkanTexture *nullTexture_ = nullptr;
VKPipeline *curPipeline_ = nullptr;
VKBuffer *curVBuffers_[4]{};
AutoRef<VKPipeline> curPipeline_;
AutoRef<VKBuffer> curVBuffers_[4];
int curVBufferOffsets_[4]{};
VKBuffer *curIBuffer_ = nullptr;
AutoRef<VKBuffer> curIBuffer_;
int curIBufferOffset_ = 0;
VkDescriptorSetLayout descriptorSetLayout_ = VK_NULL_HANDLE;
VkPipelineLayout pipelineLayout_ = VK_NULL_HANDLE;
VkPipelineCache pipelineCache_ = VK_NULL_HANDLE;
Framebuffer *curFramebuffer_ = nullptr;
AutoRef<Framebuffer> curFramebuffer_;
VkDevice device_;
VkQueue queue_;
@ -529,8 +529,8 @@ private:
enum {
MAX_FRAME_COMMAND_BUFFERS = 256,
};
VKTexture *boundTextures_[MAX_BOUND_TEXTURES]{};
VKSamplerState *boundSamplers_[MAX_BOUND_TEXTURES]{};
AutoRef<VKTexture> boundTextures_[MAX_BOUND_TEXTURES];
AutoRef<VKSamplerState> boundSamplers_[MAX_BOUND_TEXTURES];
VkImageView boundImageView_[MAX_BOUND_TEXTURES]{};
struct FrameData {

View File

@ -335,6 +335,46 @@ private:
int refcount_;
};
template <typename T>
struct AutoRef {
AutoRef() {
}
explicit AutoRef(T *p) {
ptr = p;
if (ptr)
ptr->AddRef();
}
AutoRef(const AutoRef<T> &p) {
*this = p.ptr;
}
~AutoRef() {
if (ptr)
ptr->Release();
}
T *operator =(T *p) {
if (ptr)
ptr->Release();
ptr = p;
if (ptr)
ptr->AddRef();
return ptr;
}
AutoRef<T> &operator =(const AutoRef<T> &p) {
*this = p.ptr;
return *this;
}
T *operator->() const {
return ptr;
}
operator T *() {
return ptr;
}
T *ptr = nullptr;
};
class BlendState : public RefCountedObject {
public:
};