thin3d: Add partial support for 32-bit index buffers. Add DrawIndexedUP.

This commit is contained in:
Henrik Rydgård committed 2024-11-04 23:14:22 +01:00
1 parent 0f50225f8e
commit 8f8598c347
9 files changed
+103 -10

No files matched your search

+22 -3
View File
@@ -131,6 +131,8 @@ public:
void Draw(int vertexCount, int offset) override;
void DrawIndexed(int indexCount, int offset) override;
void DrawUP(const void *vdata, int vertexCount) override;
void DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount, IndexFormat ifmt) override;
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
void BeginFrame(DebugFlags debugFlags) override;
@@ -218,6 +220,7 @@ private:
bool dirtyIndexBuffer_ = false;
ID3D11Buffer *nextIndexBuffer_ = nullptr;
DXGI_FORMAT nextIndexBufferFormat_ = DXGI_FORMAT_R16_UINT;
UINT nextIndexBufferOffset_ = 0;
InvalidationCallback invalidationCallback_;
@@ -235,6 +238,7 @@ private:
// Temporaries
ID3D11Texture2D *packTexture_ = nullptr;
Buffer *upBuffer_ = nullptr;
Buffer *upIBuffer_ = nullptr;
// System info
D3D_FEATURE_LEVEL featureLevel_;
@@ -351,6 +355,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de
const size_t UP_MAX_BYTES = 65536 * 24;
upBuffer_ = D3D11DrawContext::CreateBuffer(UP_MAX_BYTES, BufferUsageFlag::DYNAMIC | BufferUsageFlag::VERTEXDATA);
upIBuffer_ = D3D11DrawContext::CreateBuffer(UP_MAX_BYTES, BufferUsageFlag::DYNAMIC | BufferUsageFlag::INDEXDATA);
IDXGIDevice1 *dxgiDevice1 = nullptr;
hr = device_->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void **>(&dxgiDevice1));
@@ -364,6 +369,7 @@ D3D11DrawContext::~D3D11DrawContext() {
DestroyPresets();
upBuffer_->Release();
upIBuffer_->Release();
packTexture_->Release();
// Release references.
@@ -1255,7 +1261,7 @@ void D3D11DrawContext::ApplyCurrentState() {
context_->IASetVertexBuffers(0, 1, &nextVertexBuffer_, &curPipeline_->input->stride, &nextVertexBufferOffset_);
}
if (dirtyIndexBuffer_) {
context_->IASetIndexBuffer(nextIndexBuffer_, DXGI_FORMAT_R16_UINT, nextIndexBufferOffset_);
context_->IASetIndexBuffer(nextIndexBuffer_, nextIndexBufferFormat_, nextIndexBufferOffset_);
dirtyIndexBuffer_ = false;
}
if (curPipeline_->dynamicUniforms) {
@@ -1334,6 +1340,7 @@ void D3D11DrawContext::BindIndexBuffer(Buffer *indexBuffer, int offset) {
dirtyIndexBuffer_ = true;
nextIndexBuffer_ = buf ? buf->buf : 0;
nextIndexBufferOffset_ = buf ? offset : 0;
nextIndexBufferFormat_ = DXGI_FORMAT_R16_UINT;
}
void D3D11DrawContext::Draw(int vertexCount, int offset) {
@@ -1347,8 +1354,6 @@ void D3D11DrawContext::DrawIndexed(int indexCount, int offset) {
}
void D3D11DrawContext::DrawUP(const void *vdata, int vertexCount) {
ApplyCurrentState();
int byteSize = vertexCount * curPipeline_->input->stride;
UpdateBuffer(upBuffer_, (const uint8_t *)vdata, 0, byteSize, Draw::UPDATE_DISCARD);
@@ -1357,6 +1362,20 @@ void D3D11DrawContext::DrawUP(const void *vdata, int vertexCount) {
Draw(vertexCount, offset);
}
void D3D11DrawContext::DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount, IndexFormat ifmt) {
int vbyteSize = vertexCount * curPipeline_->input->stride;
int ibyteSize = indexCount * (ifmt == IndexFormat::U32 ? 4 : 2);
UpdateBuffer(upBuffer_, (const uint8_t *)vdata, 0, vbyteSize, Draw::UPDATE_DISCARD);
BindVertexBuffer(upBuffer_, 0);
UpdateBuffer(upIBuffer_, (const uint8_t *)idata, 0, ibyteSize, Draw::UPDATE_DISCARD);
BindIndexBuffer(upIBuffer_, 0);
// Override the index buffer format.
nextIndexBufferFormat_ = ifmt == IndexFormat::U32 ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;
DrawIndexed(indexCount, 0);
}
uint32_t D3D11DrawContext::GetDataFormatSupport(DataFormat fmt) const {
DXGI_FORMAT giFmt = dataFormatToD3D11(fmt);
if (giFmt == DXGI_FORMAT_UNKNOWN)
+11
View File
@@ -573,6 +573,7 @@ public:
void Draw(int vertexCount, int offset) override;
void DrawIndexed(int vertexCount, int offset) override;
void DrawUP(const void *vdata, int vertexCount) override;
void DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount, IndexFormat ifmt) override;
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
uint64_t GetNativeObject(NativeObject obj, void *srcObject) override {
@@ -1172,6 +1173,16 @@ void D3D9Context::DrawUP(const void *vdata, int vertexCount) {
device_->DrawPrimitiveUP(curPipeline_->prim, D3DPrimCount(curPipeline_->prim, vertexCount), vdata, curPipeline_->inputLayout->GetStride());
}
void D3D9Context::DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount, IndexFormat ifmt) {
curPipeline_->inputLayout->Apply(device_);
curPipeline_->Apply(device_, stencilRef_, stencilWriteMask_, stencilCompareMask_);
ApplyDynamicState();
device_->DrawIndexedPrimitiveUP(curPipeline_->prim, 0, vertexCount, D3DPrimCount(curPipeline_->prim, indexCount),
idata, ifmt == IndexFormat::U32 ? D3DFMT_INDEX32 : D3DFMT_INDEX16,
vdata, curPipeline_->inputLayout->GetStride());
}
static uint32_t SwapRB(uint32_t c) {
return (c & 0xFF00FF00) | ((c >> 16) & 0xFF) | ((c << 16) & 0xFF0000);
}
+24
View File
@@ -443,6 +443,7 @@ public:
void Draw(int vertexCount, int offset) override;
void DrawIndexed(int vertexCount, int offset) override;
void DrawUP(const void *vdata, int vertexCount) override;
void DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount, IndexFormat ifmt) override;
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
@@ -1417,6 +1418,29 @@ void OpenGLContext::DrawUP(const void *vdata, int vertexCount) {
renderManager_.Draw(curPipeline_->inputLayout->inputLayout_, buf, offset, curPipeline_->prim, 0, vertexCount);
}
void OpenGLContext::DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount, IndexFormat ifmt) {
_assert_(curPipeline_->inputLayout != nullptr);
int stride = curPipeline_->inputLayout->stride;
uint32_t vdataSize = stride * vertexCount;
uint32_t idataSize = indexCount * (ifmt == IndexFormat::U32 ? 4 : 2);
FrameData &frameData = frameData_[renderManager_.GetCurFrame()];
GLRBuffer *vbuf;
uint32_t voffset;
uint8_t *dest = frameData.push->Allocate(vdataSize, 4, &vbuf, &voffset);
memcpy(dest, vdata, vdataSize);
GLRBuffer *ibuf;
uint32_t ioffset;
dest = frameData.push->Allocate(idataSize, 4, &ibuf, &ioffset);
memcpy(dest, idata, idataSize);
ApplySamplers();
_assert_(curPipeline_->inputLayout);
renderManager_.DrawIndexed(curPipeline_->inputLayout->inputLayout_, vbuf, voffset, ibuf, ioffset, curPipeline_->prim, 0, ifmt == IndexFormat::U32 ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, vertexCount);
}
void OpenGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) {
float col[4];
Uint8x4ToFloat4(col, colorval);
+1 -1
View File
@@ -1165,7 +1165,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
VkDescriptorSet set = (*descSets)[c.drawIndexed.descSetIndex].set;
_dbg_assert_(set != VK_NULL_HANDLE);
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &set, c.drawIndexed.numUboOffsets, c.drawIndexed.uboOffsets);
vkCmdBindIndexBuffer(cmd, c.drawIndexed.ibuffer, c.drawIndexed.ioffset, VK_INDEX_TYPE_UINT16);
vkCmdBindIndexBuffer(cmd, c.drawIndexed.ibuffer, c.drawIndexed.ioffset, c.drawIndexed.itype);
VkDeviceSize voffset = c.drawIndexed.voffset;
vkCmdBindVertexBuffers(cmd, 0, 1, &c.drawIndexed.vbuffer, &voffset);
vkCmdDrawIndexed(cmd, c.drawIndexed.count, c.drawIndexed.instances, 0, 0, 0);
+1
View File
@@ -80,6 +80,7 @@ struct VkRenderData {
uint32_t voffset;
uint32_t ioffset;
uint32_t count;
VkIndexType itype; // TODO: pack this into one of the others, it's really a single bit
} drawIndexed;
struct {
uint32_t clearColor;
+2 -1
View File
@@ -471,7 +471,7 @@ public:
curRenderStep_->render.numDraws++;
}
void DrawIndexed(int descSetIndex, int numUboOffsets, const uint32_t *uboOffsets, VkBuffer vbuffer, int voffset, VkBuffer ibuffer, int ioffset, int count, int numInstances) {
void DrawIndexed(int descSetIndex, int numUboOffsets, const uint32_t *uboOffsets, VkBuffer vbuffer, int voffset, VkBuffer ibuffer, int ioffset, int count, int numInstances, VkIndexType itype) {
_dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER && curStepHasViewport_ && curStepHasScissor_);
VkRenderData &data = curRenderStep_->commands.push_uninitialized();
data.cmd = VKRRenderCommand::DRAW_INDEXED;
@@ -483,6 +483,7 @@ public:
data.drawIndexed.ibuffer = ibuffer;
data.drawIndexed.ioffset = ioffset;
data.drawIndexed.numUboOffsets = numUboOffsets;
data.drawIndexed.itype = itype;
_dbg_assert_(numUboOffsets <= ARRAY_SIZE(data.drawIndexed.uboOffsets));
for (int i = 0; i < numUboOffsets; i++)
data.drawIndexed.uboOffsets[i] = uboOffsets[i];
+33 -2
View File
@@ -491,6 +491,7 @@ public:
void Draw(int vertexCount, int offset) override;
void DrawIndexed(int vertexCount, int offset) override;
void DrawUP(const void *vdata, int vertexCount) override;
void DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount, IndexFormat ifmt) override;
void BindCurrentPipeline();
void ApplyDynamicState();
@@ -1497,7 +1498,7 @@ void VKContext::DrawIndexed(int vertexCount, int offset) {
int descSetIndex;
PackedDescriptor *descriptors = renderManager_.PushDescriptorSet(4, &descSetIndex);
BindDescriptors(vulkanUBObuf, descriptors);
renderManager_.DrawIndexed(descSetIndex, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffset_, vulkanIbuf, (int)ibBindOffset + offset * sizeof(uint32_t), vertexCount, 1);
renderManager_.DrawIndexed(descSetIndex, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffset_, vulkanIbuf, (int)ibBindOffset + offset * sizeof(uint32_t), vertexCount, 1, VK_INDEX_TYPE_UINT16);
}
void VKContext::DrawUP(const void *vdata, int vertexCount) {
@@ -1520,7 +1521,37 @@ void VKContext::DrawUP(const void *vdata, int vertexCount) {
int descSetIndex;
PackedDescriptor *descriptors = renderManager_.PushDescriptorSet(4, &descSetIndex);
BindDescriptors(vulkanUBObuf, descriptors);
renderManager_.Draw(descSetIndex, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffset_, vertexCount);
renderManager_.Draw(descSetIndex, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset, vertexCount);
}
void VKContext::DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount, IndexFormat ifmt) {
_dbg_assert_(vertexCount >= 0);
_dbg_assert_(indexCount >= 0);
if (vertexCount <= 0 || indexCount <= 0) {
return;
}
VkBuffer vulkanVbuf, vulkanIbuf, vulkanUBObuf;
size_t vdataSize = vertexCount * curPipeline_->stride;
uint32_t vbBindOffset;
uint8_t *vdataPtr = push_->Allocate(vdataSize, 4, &vulkanVbuf, &vbBindOffset);
_assert_(vdataPtr != nullptr);
memcpy(vdataPtr, vdata, vdataSize);
size_t idataSize = indexCount * (ifmt == IndexFormat::U32 ? 4 : 2);
uint32_t ibBindOffset;
uint8_t *idataPtr = push_->Allocate(idataSize, 4, &vulkanIbuf, &ibBindOffset);
_assert_(idataPtr != nullptr);
memcpy(idataPtr, vdata, idataSize);
uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf);
BindCurrentPipeline();
ApplyDynamicState();
int descSetIndex;
PackedDescriptor *descriptors = renderManager_.PushDescriptorSet(4, &descSetIndex);
BindDescriptors(vulkanUBObuf, descriptors);
renderManager_.DrawIndexed(descSetIndex, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset, vulkanIbuf, (int)ibBindOffset, indexCount, 1, ifmt == IndexFormat::U32 ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16);
}
void VKContext::BindCurrentPipeline() {
+7 -1
View File
@@ -180,6 +180,11 @@ enum class Facing {
CW,
};
enum class IndexFormat {
U16,
U32,
};
enum BorderColor {
DONT_CARE,
TRANSPARENT_BLACK,
@@ -827,7 +832,8 @@ public:
virtual void Draw(int vertexCount, int offset) = 0;
virtual void DrawIndexed(int vertexCount, int offset) = 0; // Always 16-bit indices.
virtual void DrawUP(const void *vdata, int vertexCount) = 0;
virtual void DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount, IndexFormat ifmt) = 0; // Supports 32-bit indices, for IMGUI use.
// Frame management (for the purposes of sync and resource management, necessary with modern APIs). Default implementations here.
virtual void BeginFrame(DebugFlags debugFlags) = 0;
virtual void EndFrame() = 0;
+2 -2
View File
@@ -374,7 +374,7 @@ void DrawEngineVulkan::DoFlush() {
if (!ibuf) {
ibOffset = (uint32_t)pushIndex_->Push(decIndex_, sizeof(uint16_t) * vertexCount, 4, &ibuf);
}
renderManager->DrawIndexed(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, 1);
renderManager->DrawIndexed(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, 1, VK_INDEX_TYPE_UINT16);
} else {
renderManager->Draw(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, vertexCount);
}
@@ -539,7 +539,7 @@ void DrawEngineVulkan::DoFlush() {
VkBuffer vbuf, ibuf;
vbOffset = (uint32_t)pushVertex_->Push(result.drawBuffer, numDecodedVerts_ * sizeof(TransformedVertex), 4, &vbuf);
ibOffset = (uint32_t)pushIndex_->Push(inds, sizeof(short) * result.drawNumTrans, 4, &ibuf);
renderManager->DrawIndexed(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, result.drawNumTrans, 1);
renderManager->DrawIndexed(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, result.drawNumTrans, 1, VK_INDEX_TYPE_UINT16);
} else if (result.action == SW_CLEAR) {
// Note: we won't get here if the clear is alpha but not color, or color but not alpha.
bool clearColor = gstate.isClearModeColorMask();