Remove the concept of push constants

BUG=dawn:14

Change-Id: I20587081ec806034ce4f90457c3d475a6fbe834d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/7180
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Corentin Wallez
2019-05-29 13:16:06 +00:00
committed by Commit Bot service account
parent 839053b90c
commit 8dfc593eb7
24 changed files with 68 additions and 1095 deletions

View File

@@ -138,77 +138,6 @@ namespace dawn_native { namespace opengl {
}
}
// Push constants are implemented using OpenGL uniforms, however they aren't part of the
// global OpenGL state but are part of the program state instead. This means that we have to
// reapply push constants on pipeline change.
//
// This structure tracks the current values of push constants as well as dirty bits for push
// constants that should be applied before the next draw or dispatch.
class PushConstantTracker {
public:
PushConstantTracker() {
for (auto stage : IterateStages(kAllStages)) {
mValues[stage].fill(0);
// No need to set dirty bits as a pipeline will be set before the next operation
// using push constants.
}
}
void OnSetPushConstants(dawn::ShaderStageBit stages,
uint32_t count,
uint32_t offset,
const uint32_t* data) {
for (auto stage : IterateStages(stages)) {
memcpy(&mValues[stage][offset], data, count * sizeof(uint32_t));
// Use 64 bit masks and make sure there are no shift UB
static_assert(kMaxPushConstants <= 8 * sizeof(unsigned long long) - 1, "");
mDirtyBits[stage] |= ((1ull << count) - 1ull) << offset;
}
}
void OnSetPipeline(PipelineBase* pipeline) {
for (auto stage : IterateStages(kAllStages)) {
mDirtyBits[stage] = pipeline->GetPushConstants(stage).mask;
}
}
void Apply(PipelineBase* pipeline, PipelineGL* glPipeline) {
for (auto stage : IterateStages(kAllStages)) {
const auto& pushConstants = pipeline->GetPushConstants(stage);
const auto& glPushConstants = glPipeline->GetGLPushConstants(stage);
for (uint32_t constant :
IterateBitSet(mDirtyBits[stage] & pushConstants.mask)) {
GLint location = glPushConstants[constant];
switch (pushConstants.types[constant]) {
case PushConstantType::Int:
glUniform1i(location,
*reinterpret_cast<GLint*>(&mValues[stage][constant]));
break;
case PushConstantType::UInt:
glUniform1ui(location,
*reinterpret_cast<GLuint*>(&mValues[stage][constant]));
break;
case PushConstantType::Float:
float value;
// Use a memcpy to avoid strict-aliasing warnings, even if it is
// still technically undefined behavior.
memcpy(&value, &mValues[stage][constant], sizeof(value));
glUniform1f(location, value);
break;
}
}
mDirtyBits[stage].reset();
}
}
private:
PerStage<std::array<uint32_t, kMaxPushConstants>> mValues;
PerStage<std::bitset<kMaxPushConstants>> mDirtyBits;
};
// Vertex buffers and index buffers are implemented as part of an OpenGL VAO that
// corresponds to an VertexInput. On the contrary in Dawn they are part of the global state.
// This means that we have to re-apply these buffers on an VertexInput change.
@@ -555,7 +484,6 @@ namespace dawn_native { namespace opengl {
}
void CommandBuffer::ExecuteComputePass() {
PushConstantTracker pushConstants;
ComputePipeline* lastPipeline = nullptr;
Command type;
@@ -568,7 +496,6 @@ namespace dawn_native { namespace opengl {
case Command::Dispatch: {
DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();
pushConstants.Apply(lastPipeline, lastPipeline);
glDispatchCompute(dispatch->x, dispatch->y, dispatch->z);
// TODO(cwallez@chromium.org): add barriers to the API
glMemoryBarrier(GL_ALL_BARRIER_BITS);
@@ -577,15 +504,7 @@ namespace dawn_native { namespace opengl {
case Command::SetComputePipeline: {
SetComputePipelineCmd* cmd = mCommands.NextCommand<SetComputePipelineCmd>();
lastPipeline = ToBackend(cmd->pipeline).Get();
lastPipeline->ApplyNow();
pushConstants.OnSetPipeline(lastPipeline);
} break;
case Command::SetPushConstants: {
SetPushConstantsCmd* cmd = mCommands.NextCommand<SetPushConstantsCmd>();
uint32_t* data = mCommands.NextData<uint32_t>(cmd->count);
pushConstants.OnSetPushConstants(cmd->stages, cmd->count, cmd->offset, data);
} break;
case Command::SetBindGroup: {
@@ -732,7 +651,6 @@ namespace dawn_native { namespace opengl {
RenderPipeline* lastPipeline = nullptr;
uint64_t indexBufferBaseOffset = 0;
PushConstantTracker pushConstants;
InputBufferTracker inputBuffers;
Command type;
@@ -751,7 +669,6 @@ namespace dawn_native { namespace opengl {
case Command::Draw: {
DrawCmd* draw = mCommands.NextCommand<DrawCmd>();
pushConstants.Apply(lastPipeline, lastPipeline);
inputBuffers.Apply();
if (draw->firstInstance > 0) {
@@ -768,7 +685,6 @@ namespace dawn_native { namespace opengl {
case Command::DrawIndexed: {
DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>();
pushConstants.Apply(lastPipeline, lastPipeline);
inputBuffers.Apply();
dawn::IndexFormat indexFormat =
@@ -805,16 +721,9 @@ namespace dawn_native { namespace opengl {
lastPipeline = ToBackend(cmd->pipeline).Get();
lastPipeline->ApplyNow(persistentPipelineState);
pushConstants.OnSetPipeline(lastPipeline);
inputBuffers.OnSetPipeline(lastPipeline);
} break;
case Command::SetPushConstants: {
SetPushConstantsCmd* cmd = mCommands.NextCommand<SetPushConstantsCmd>();
uint32_t* data = mCommands.NextData<uint32_t>(cmd->count);
pushConstants.OnSetPushConstants(cmd->stages, cmd->count, cmd->offset, data);
} break;
case Command::SetStencilReference: {
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
persistentPipelineState.SetStencilReference(cmd->reference);

View File

@@ -70,29 +70,6 @@ namespace dawn_native { namespace opengl {
return shader;
};
auto FillPushConstants = [](const ShaderModule* module, GLPushConstantInfo* info,
GLuint program) {
const auto& moduleInfo = module->GetPushConstants();
for (uint32_t i = 0; i < moduleInfo.names.size(); i++) {
(*info)[i] = -1;
unsigned int size = moduleInfo.sizes[i];
if (size == 0) {
continue;
}
GLint location = glGetUniformLocation(program, moduleInfo.names[i].c_str());
if (location == -1) {
continue;
}
for (uint32_t offset = 0; offset < size; offset++) {
(*info)[i + offset] = location + offset;
}
i += size - 1;
}
};
mProgram = glCreateProgram();
dawn::ShaderStageBit activeStages = dawn::ShaderStageBit::None;
@@ -123,10 +100,6 @@ namespace dawn_native { namespace opengl {
}
}
for (dawn::ShaderStage stage : IterateStages(activeStages)) {
FillPushConstants(modules[stage], &mGlPushConstants[stage], mProgram);
}
glUseProgram(mProgram);
// The uniforms are part of the program state so we can pre-bind buffer units, texture units
@@ -200,11 +173,6 @@ namespace dawn_native { namespace opengl {
}
}
const PipelineGL::GLPushConstantInfo& PipelineGL::GetGLPushConstants(
dawn::ShaderStage stage) const {
return mGlPushConstants[stage];
}
const std::vector<GLuint>& PipelineGL::GetTextureUnitsForSampler(GLuint index) const {
ASSERT(index < mUnitsForSamplers.size());
return mUnitsForSamplers[index];

View File

@@ -34,11 +34,9 @@ namespace dawn_native { namespace opengl {
void Initialize(const PipelineLayout* layout, const PerStage<const ShaderModule*>& modules);
using GLPushConstantInfo = std::array<GLint, kMaxPushConstants>;
using BindingLocations =
std::array<std::array<GLint, kMaxBindingsPerGroup>, kMaxBindGroups>;
const GLPushConstantInfo& GetGLPushConstants(dawn::ShaderStage stage) const;
const std::vector<GLuint>& GetTextureUnitsForSampler(GLuint index) const;
const std::vector<GLuint>& GetTextureUnitsForTextureView(GLuint index) const;
GLuint GetProgramHandle() const;
@@ -47,7 +45,6 @@ namespace dawn_native { namespace opengl {
private:
GLuint mProgram;
PerStage<GLPushConstantInfo> mGlPushConstants;
std::vector<std::vector<GLuint>> mUnitsForSamplers;
std::vector<std::vector<GLuint>> mUnitsForTextures;
};