Draw primitive now settable via pipeline object

This commit is contained in:
Jack Andersen 2016-03-23 22:05:19 -10:00
parent ca38805776
commit 6600ff208c
9 changed files with 69 additions and 35 deletions

View File

@ -27,7 +27,7 @@ public:
virtual IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, virtual IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
ComPtr<ID3DBlob>& vertBlobOut, ComPtr<ID3DBlob>& fragBlobOut, ComPtr<ID3DBlob>& vertBlobOut, ComPtr<ID3DBlob>& fragBlobOut,
ComPtr<ID3DBlob>& pipelineBlob, IVertexFormat* vtxFmt, ComPtr<ID3DBlob>& pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling)=0; bool depthTest, bool depthWrite, bool backfaceCulling)=0;
}; };

View File

@ -50,7 +50,7 @@ public:
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
size_t texCount, const char* texArrayName, size_t texCount, const char* texArrayName,
size_t uniformBlockCount, const char** uniformBlockNames, size_t uniformBlockCount, const char** uniformBlockNames,
BlendFactor srcFac, BlendFactor dstFac, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling); bool depthTest, bool depthWrite, bool backfaceCulling);
IShaderDataBinding* IShaderDataBinding*

View File

@ -155,6 +155,13 @@ struct IShaderDataBinding {};
struct IGraphicsData {}; struct IGraphicsData {};
class GraphicsDataToken; class GraphicsDataToken;
/** Used by platform shader pipeline constructors */
enum class Primitive
{
Triangles,
TriStrips
};
/** Used by platform shader pipeline constructors */ /** Used by platform shader pipeline constructors */
enum class BlendFactor enum class BlendFactor
{ {

View File

@ -57,7 +57,7 @@ public:
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
IVertexFormat* vtxFmt, unsigned targetSamples, IVertexFormat* vtxFmt, unsigned targetSamples,
BlendFactor srcFac, BlendFactor dstFac, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling); bool depthTest, bool depthWrite, bool backfaceCulling);
IShaderDataBinding* IShaderDataBinding*

View File

@ -110,7 +110,7 @@ public:
bool depthTest, bool depthWrite, bool backfaceCulling); bool depthTest, bool depthWrite, bool backfaceCulling);
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt, IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling) bool depthTest, bool depthWrite, bool backfaceCulling)
{ {
std::vector<unsigned int> vertBlob; std::vector<unsigned int> vertBlob;

View File

@ -43,17 +43,17 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
std::mutex m_engineMutex; std::mutex m_engineMutex;
std::condition_variable m_engineCv; std::condition_variable m_engineCv;
static void Callback(AQSAudioVoiceEngine* voice, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) static void Callback(AQSAudioVoiceEngine* engine, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
{ {
std::unique_lock<std::mutex> lk(voice->m_engineMutex); std::unique_lock<std::mutex> lk(engine->m_engineMutex);
voice->m_engineCv.wait(lk); engine->m_engineCv.wait(lk);
voice->_pumpAndMixVoices(voice->m_mixInfo.m_periodFrames, reinterpret_cast<int32_t*>(inBuffer->mAudioData)); engine->_pumpAndMixVoices(engine->m_mixInfo.m_periodFrames, reinterpret_cast<int32_t*>(inBuffer->mAudioData));
inBuffer->mAudioDataByteSize = voice->m_frameBytes; inBuffer->mAudioDataByteSize = engine->m_frameBytes;
AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, nullptr); AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, nullptr);
} }
static void DummyCallback(AQSAudioVoiceEngine* voice, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {} static void DummyCallback(AQSAudioVoiceEngine* engine, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {}
AudioChannelSet _getAvailableSet() AudioChannelSet _getAvailableSet()
{ {

View File

@ -338,12 +338,14 @@ GLDataFactory::newStaticArrayTexture(size_t width, size_t height, size_t layers,
class GLShaderPipeline : public IShaderPipeline class GLShaderPipeline : public IShaderPipeline
{ {
friend class GLDataFactory; friend class GLDataFactory;
friend class GLCommandQueue;
friend struct GLShaderDataBinding; friend struct GLShaderDataBinding;
GLuint m_vert = 0; GLuint m_vert = 0;
GLuint m_frag = 0; GLuint m_frag = 0;
GLuint m_prog = 0; GLuint m_prog = 0;
GLenum m_sfactor = GL_ONE; GLenum m_sfactor = GL_ONE;
GLenum m_dfactor = GL_ZERO; GLenum m_dfactor = GL_ZERO;
GLenum m_drawPrim = GL_TRIANGLES;
bool m_depthTest = true; bool m_depthTest = true;
bool m_depthWrite = true; bool m_depthWrite = true;
bool m_backfaceCulling = true; bool m_backfaceCulling = true;
@ -396,6 +398,7 @@ public:
m_depthWrite = other.m_depthWrite; m_depthWrite = other.m_depthWrite;
m_backfaceCulling = other.m_backfaceCulling; m_backfaceCulling = other.m_backfaceCulling;
m_uniLocs = std::move(other.m_uniLocs); m_uniLocs = std::move(other.m_uniLocs);
m_drawPrim = other.m_drawPrim;
return *this; return *this;
} }
GLShaderPipeline(GLShaderPipeline&& other) {*this = std::move(other);} GLShaderPipeline(GLShaderPipeline&& other) {*this = std::move(other);}
@ -427,6 +430,12 @@ public:
} }
}; };
static const GLenum PRIMITIVE_TABLE[] =
{
GL_TRIANGLES,
GL_TRIANGLE_STRIP
};
static const GLenum BLEND_FACTOR_TABLE[] = static const GLenum BLEND_FACTOR_TABLE[] =
{ {
GL_ZERO, GL_ZERO,
@ -447,7 +456,7 @@ IShaderPipeline* GLDataFactory::newShaderPipeline
(const char* vertSource, const char* fragSource, (const char* vertSource, const char* fragSource,
size_t texCount, const char* texArrayName, size_t texCount, const char* texArrayName,
size_t uniformBlockCount, const char** uniformBlockNames, size_t uniformBlockCount, const char** uniformBlockNames,
BlendFactor srcFac, BlendFactor dstFac, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling) bool depthTest, bool depthWrite, bool backfaceCulling)
{ {
GLShaderPipeline shader; GLShaderPipeline shader;
@ -461,6 +470,7 @@ IShaderPipeline* GLDataFactory::newShaderPipeline
shader.m_depthTest = depthTest; shader.m_depthTest = depthTest;
shader.m_depthWrite = depthWrite; shader.m_depthWrite = depthWrite;
shader.m_backfaceCulling = backfaceCulling; shader.m_backfaceCulling = backfaceCulling;
shader.m_drawPrim = PRIMITIVE_TABLE[int(prim)];
glShaderSource(shader.m_vert, 1, &vertSource, nullptr); glShaderSource(shader.m_vert, 1, &vertSource, nullptr);
glCompileShader(shader.m_vert); glCompileShader(shader.m_vert);
@ -929,13 +939,18 @@ struct GLCommandQueue : IGraphicsCommandQueue
posts.swap(self->m_pendingPosts2); posts.swap(self->m_pendingPosts2);
} }
std::vector<Command>& cmds = self->m_cmdBufs[self->m_drawBuf]; std::vector<Command>& cmds = self->m_cmdBufs[self->m_drawBuf];
GLenum currentPrim = GL_TRIANGLES;
for (const Command& cmd : cmds) for (const Command& cmd : cmds)
{ {
switch (cmd.m_op) switch (cmd.m_op)
{ {
case Command::Op::SetShaderDataBinding: case Command::Op::SetShaderDataBinding:
static_cast<const GLShaderDataBinding*>(cmd.binding)->bind(self->m_drawBuf); {
const GLShaderDataBinding* binding = static_cast<const GLShaderDataBinding*>(cmd.binding);
binding->bind(self->m_drawBuf);
currentPrim = binding->m_pipeline->m_drawPrim;
break; break;
}
case Command::Op::SetRenderTarget: case Command::Op::SetRenderTarget:
{ {
const GLTextureR* tex = static_cast<const GLTextureR*>(cmd.target); const GLTextureR* tex = static_cast<const GLTextureR*>(cmd.target);
@ -966,16 +981,16 @@ struct GLCommandQueue : IGraphicsCommandQueue
glClear(cmd.flags); glClear(cmd.flags);
break; break;
case Command::Op::Draw: case Command::Op::Draw:
glDrawArrays(GL_TRIANGLE_STRIP, cmd.start, cmd.count); glDrawArrays(currentPrim, cmd.start, cmd.count);
break; break;
case Command::Op::DrawIndexed: case Command::Op::DrawIndexed:
glDrawElements(GL_TRIANGLE_STRIP, cmd.count, GL_UNSIGNED_INT, (void*)cmd.start); glDrawElements(currentPrim, cmd.count, GL_UNSIGNED_INT, (void*)cmd.start);
break; break;
case Command::Op::DrawInstances: case Command::Op::DrawInstances:
glDrawArraysInstanced(GL_TRIANGLE_STRIP, cmd.start, cmd.count, cmd.instCount); glDrawArraysInstanced(currentPrim, cmd.start, cmd.count, cmd.instCount);
break; break;
case Command::Op::DrawInstancesIndexed: case Command::Op::DrawInstancesIndexed:
glDrawElementsInstanced(GL_TRIANGLE_STRIP, cmd.count, GL_UNSIGNED_INT, (void*)cmd.start, cmd.instCount); glDrawElementsInstanced(currentPrim, cmd.count, GL_UNSIGNED_INT, (void*)cmd.start, cmd.instCount);
break; break;
case Command::Op::ResolveBindTexture: case Command::Op::ResolveBindTexture:
{ {

View File

@ -417,15 +417,24 @@ static const MTLBlendFactor BLEND_FACTOR_TABLE[] =
MTLBlendFactorOneMinusDestinationAlpha MTLBlendFactorOneMinusDestinationAlpha
}; };
static const MTLPrimitiveType PRIMITIVE_TABLE[] =
{
MTLPrimitiveTypeTriangle,
MTLPrimitiveTypeTriangleStrip
};
class MetalShaderPipeline : public IShaderPipeline class MetalShaderPipeline : public IShaderPipeline
{ {
friend class MetalDataFactory; friend class MetalDataFactory;
friend class MetalCommandQueue;
MTLCullMode m_cullMode = MTLCullModeNone; MTLCullMode m_cullMode = MTLCullModeNone;
MTLPrimitiveType m_drawPrim;
MetalShaderPipeline(MetalContext* ctx, id<MTLFunction> vert, id<MTLFunction> frag, MetalShaderPipeline(MetalContext* ctx, id<MTLFunction> vert, id<MTLFunction> frag,
const MetalVertexFormat* vtxFmt, NSUInteger targetSamples, const MetalVertexFormat* vtxFmt, NSUInteger targetSamples,
BlendFactor srcFac, BlendFactor dstFac, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling) bool depthTest, bool depthWrite, bool backfaceCulling)
: m_drawPrim(PRIMITIVE_TABLE[int(prim)])
{ {
if (backfaceCulling) if (backfaceCulling)
m_cullMode = MTLCullModeBack; m_cullMode = MTLCullModeBack;
@ -591,11 +600,13 @@ struct MetalCommandQueue : IGraphicsCommandQueue
} }
MetalShaderDataBinding* m_boundData = nullptr; MetalShaderDataBinding* m_boundData = nullptr;
MTLPrimitiveType m_currentPrimitive = MTLPrimitiveTypeTriangle;
void setShaderDataBinding(IShaderDataBinding* binding) void setShaderDataBinding(IShaderDataBinding* binding)
{ {
MetalShaderDataBinding* cbind = static_cast<MetalShaderDataBinding*>(binding); MetalShaderDataBinding* cbind = static_cast<MetalShaderDataBinding*>(binding);
cbind->bind(m_enc, m_fillBuf); cbind->bind(m_enc, m_fillBuf);
m_boundData = cbind; m_boundData = cbind;
m_currentPrimitive = cbind->m_pipeline->m_drawPrim;
} }
MetalTextureR* m_boundTarget = nullptr; MetalTextureR* m_boundTarget = nullptr;
@ -661,12 +672,12 @@ struct MetalCommandQueue : IGraphicsCommandQueue
void draw(size_t start, size_t count) void draw(size_t start, size_t count)
{ {
[m_enc drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:start vertexCount:count]; [m_enc drawPrimitives:m_currentPrimitive vertexStart:start vertexCount:count];
} }
void drawIndexed(size_t start, size_t count) void drawIndexed(size_t start, size_t count)
{ {
[m_enc drawIndexedPrimitives:MTLPrimitiveTypeTriangleStrip [m_enc drawIndexedPrimitives:m_currentPrimitive
indexCount:count indexCount:count
indexType:MTLIndexTypeUInt32 indexType:MTLIndexTypeUInt32
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf) indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
@ -675,13 +686,13 @@ struct MetalCommandQueue : IGraphicsCommandQueue
void drawInstances(size_t start, size_t count, size_t instCount) void drawInstances(size_t start, size_t count, size_t instCount)
{ {
[m_enc drawPrimitives:MTLPrimitiveTypeTriangleStrip [m_enc drawPrimitives:m_currentPrimitive
vertexStart:start vertexCount:count instanceCount:instCount]; vertexStart:start vertexCount:count instanceCount:instCount];
} }
void drawInstancesIndexed(size_t start, size_t count, size_t instCount) void drawInstancesIndexed(size_t start, size_t count, size_t instCount)
{ {
[m_enc drawIndexedPrimitives:MTLPrimitiveTypeTriangleStrip [m_enc drawIndexedPrimitives:m_currentPrimitive
indexCount:count indexCount:count
indexType:MTLIndexTypeUInt32 indexType:MTLIndexTypeUInt32
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf) indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
@ -951,7 +962,7 @@ IVertexFormat* MetalDataFactory::newVertexFormat(size_t elementCount, const Vert
IShaderPipeline* MetalDataFactory::newShaderPipeline(const char* vertSource, const char* fragSource, IShaderPipeline* MetalDataFactory::newShaderPipeline(const char* vertSource, const char* fragSource,
IVertexFormat* vtxFmt, unsigned targetSamples, IVertexFormat* vtxFmt, unsigned targetSamples,
BlendFactor srcFac, BlendFactor dstFac, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling) bool depthTest, bool depthWrite, bool backfaceCulling)
{ {
MTLCompileOptions* compOpts = [MTLCompileOptions new]; MTLCompileOptions* compOpts = [MTLCompileOptions new];
@ -974,7 +985,7 @@ IShaderPipeline* MetalDataFactory::newShaderPipeline(const char* vertSource, con
MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc, fragFunc, MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc, fragFunc,
static_cast<const MetalVertexFormat*>(vtxFmt), targetSamples, static_cast<const MetalVertexFormat*>(vtxFmt), targetSamples,
srcFac, dstFac, depthTest, depthWrite, backfaceCulling); srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling);
if (!m_deferredData.get()) if (!m_deferredData.get())
m_deferredData.reset(new struct MetalData()); m_deferredData.reset(new struct MetalData());
m_deferredData->m_SPs.emplace_back(retval); m_deferredData->m_SPs.emplace_back(retval);

View File

@ -126,7 +126,7 @@ struct CTestWindowCallback : IWindowCallback
SWindowRect m_lastRect; SWindowRect m_lastRect;
bool m_rectDirty = false; bool m_rectDirty = false;
bool m_windowInvalid = false; bool m_windowInvalid = false;
void resized(const SWindowRect& rect) void resized(const SWindowRect& rect)
{ {
m_lastRect = rect; m_lastRect = rect;
@ -209,7 +209,7 @@ struct CTestWindowCallback : IWindowCallback
} }
}; };
struct TestApplicationCallback : IApplicationCallback struct TestApplicationCallback : IApplicationCallback
{ {
IWindow* mainWindow; IWindow* mainWindow;
@ -219,19 +219,19 @@ struct TestApplicationCallback : IApplicationCallback
IShaderDataBinding* m_binding = nullptr; IShaderDataBinding* m_binding = nullptr;
ITextureR* m_renderTarget = nullptr; ITextureR* m_renderTarget = nullptr;
std::mutex m_mt; std::mutex m_mt;
std::condition_variable m_cv; std::condition_variable m_cv;
std::mutex m_initmt; std::mutex m_initmt;
std::condition_variable m_initcv; std::condition_variable m_initcv;
static void LoaderProc(TestApplicationCallback* self) static void LoaderProc(TestApplicationCallback* self)
{ {
std::unique_lock<std::mutex> lk(self->m_initmt); std::unique_lock<std::mutex> lk(self->m_initmt);
IGraphicsDataFactory* factory = self->mainWindow->getLoadContextDataFactory(); IGraphicsDataFactory* factory = self->mainWindow->getLoadContextDataFactory();
/* Create render target */ /* Create render target */
int x, y, w, h; int x, y, w, h;
self->mainWindow->getWindowFrame(x, y, w, h); self->mainWindow->getWindowFrame(x, y, w, h);
@ -306,7 +306,7 @@ struct TestApplicationCallback : IApplicationCallback
pipeline = glF->newShaderPipeline(VS, FS, 1, "texs", 0, nullptr, pipeline = glF->newShaderPipeline(VS, FS, 1, "texs", 0, nullptr,
BlendFactor::One, BlendFactor::Zero, BlendFactor::One, BlendFactor::Zero,
true, true, false); Primitive::TriStrips, true, true, false);
} }
#if _WIN32 #if _WIN32
else if (factory->platform() == IGraphicsDataFactory::Platform::D3D12 || else if (factory->platform() == IGraphicsDataFactory::Platform::D3D12 ||
@ -344,7 +344,7 @@ struct TestApplicationCallback : IApplicationCallback
else if (factory->platform() == IGraphicsDataFactory::Platform::Metal) else if (factory->platform() == IGraphicsDataFactory::Platform::Metal)
{ {
MetalDataFactory* metalF = dynamic_cast<MetalDataFactory*>(factory); MetalDataFactory* metalF = dynamic_cast<MetalDataFactory*>(factory);
static const char* VS = static const char* VS =
"#include <metal_stdlib>\n" "#include <metal_stdlib>\n"
"using namespace metal;\n" "using namespace metal;\n"
@ -357,7 +357,7 @@ struct TestApplicationCallback : IApplicationCallback
" retval.out_uv = v.in_uv;\n" " retval.out_uv = v.in_uv;\n"
" return retval;\n" " return retval;\n"
"}\n"; "}\n";
static const char* FS = static const char* FS =
"#include <metal_stdlib>\n" "#include <metal_stdlib>\n"
"using namespace metal;\n" "using namespace metal;\n"
@ -367,9 +367,10 @@ struct TestApplicationCallback : IApplicationCallback
"{\n" "{\n"
" return tex.sample(samp, d.out_uv);\n" " return tex.sample(samp, d.out_uv);\n"
"}\n"; "}\n";
pipeline = metalF->newShaderPipeline(VS, FS, vfmt, 1, pipeline = metalF->newShaderPipeline(VS, FS, vfmt, 1,
BlendFactor::One, BlendFactor::Zero, true, true, false); BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips,
true, true, false);
} }
#endif #endif
@ -379,7 +380,7 @@ struct TestApplicationCallback : IApplicationCallback
/* Commit objects */ /* Commit objects */
GraphicsDataToken data = factory->commit(); GraphicsDataToken data = factory->commit();
/* Return control to client */ /* Return control to client */
lk.unlock(); lk.unlock();
self->m_initcv.notify_one(); self->m_initcv.notify_one();